Menu
Coddy logo textTech

포인터 vs 값

Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 9번째.

구조체를 함수에 전달할 때, C 언어는 두 가지 옵션을 제공합니다: 값에 의한 전달(전체 구조체 복사) 또는 포인터에 의한 전달(주소만 복사)입니다. 이 선택은 성능에 큰 영향을 미칩니다.

값에 의한 전달(Passing by value)은 스택에 구조체의 전체 복사본을 생성합니다. 몇 개의 정수를 가진 작은 구조체의 경우 이는 괜찮습니다. 하지만 수백 바이트 크기의 구조체를 상상해 보십시오. 함수를 호출할 때마다 그 모든 데이터를 복사하게 됩니다.

typedef struct {
    char name[100];
    int scores[50];
    double average;
} Student;

// 값 전달: 호출할 때마다 약 608바이트를 복사합니다.
void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);
}

// 포인터 전달: 오직 8바이트(주소값)만 복사합니다.
void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);
}

구문도 다릅니다. 값 매개변수를 사용하면 점 연산자(s.name)를 사용합니다. 포인터를 사용하면 화살표 연산자(s->name)를 사용합니다.

포인터 버전은 메모리 주소만 전달하기 때문에 더 효율적입니다. 이는 구조체(struct) 크기에 관계없이 일반적으로 8바이트입니다.

이것이 C 프로그래머들이 거의 항상 구조체를 포인터로 전달하는 이유입니다. 함수가 데이터를 수정하지 않아야 할 때는 const를 사용하고, 수정해야 할 때는 일반 포인터를 사용하세요. 효율성과 명확한 의도를 모두 얻을 수 있습니다.

challenge icon

챌린지

쉬움

구조체를 값으로 전달하는 것과 포인터로 전달하는 것의 차이를 보여주는 Product 모듈을 만들어 보겠습니다. 전체 구조체를 복사본으로 받는 함수와 구조체에 대한 포인터만 받는 함수, 이렇게 두 개의 출력 함수를 작성하게 됩니다.

세 개의 파일을 생성해야 합니다:

  • product.h: 세 개의 멤버 char name[50], double price, int quantity를 가진 Product 구조체를 선언합니다. 또한 다음 두 함수를 선언합니다:
    • display_by_valueProduct를 값으로 전달받아 정보를 출력합니다.
    • display_by_pointerconst Product *를 전달받아 동일한 정보를 출력합니다.
    PRODUCT_H 심볼을 사용하여 include guard를 적용하세요.
  • product.c: 두 함수를 구현합니다. 구문의 차이점에 주의하세요. 값 전달 방식은 점 연산자(p.name)를 사용하고, 포인터 방식은 화살표 연산자(p->name)를 사용합니다. 두 함수 모두 동일한 형식으로 출력해야 합니다.
  • main.c: Product를 생성한 다음, 서로 다른 매개변수 스타일을 사용함에도 불구하고 동일한 출력을 생성하는지 확인하기 위해 두 출력 함수를 모두 호출합니다.

세 가지 입력을 받게 됩니다: 제품 이름 (문자열), 가격 (double), 수량 (정수).

메인 파일에서 이 값들로 Product를 초기화한 다음, display_by_value를 호출하고 이어서 display_by_pointer를 호출하세요.

두 함수 모두 다음 형식으로 출력해야 합니다:

Product: {name}, Price: {price}, Qty: {quantity}

가격은 소수점 둘째 자리까지 표시하도록 %.2f를 사용하세요.

예를 들어, 입력값이 Laptop, 999.99, 5인 경우 출력은 다음과 같습니다:

Product: Laptop, Price: 999.99, Qty: 5
Product: Laptop, Price: 999.99, Qty: 5

치트 시트

구조체를 함수에 전달할 때, 값에 의한 전달(전체 구조체 복사) 또는 포인터에 의한 전달(주소만 복사) 중 하나를 선택할 수 있습니다.

값에 의한 전달은 구조체의 전체 복사본을 생성합니다:

void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);  // 점 연산자 사용
}

포인터에 의한 전달은 메모리 주소만 전달합니다:

void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);  // 화살표 연산자 사용
}

주요 차이점:

  • 값에 의한 전달은 점 연산자(s.member)를 사용합니다.
  • 포인터에 의한 전달은 화살표 연산자(s->member)를 사용합니다.
  • 포인터는 큰 구조체에 대해 더 효율적입니다 (전체 구조체 크기 대신 8바이트만 사용).
  • 함수가 데이터를 수정하지 않아야 할 때는 포인터와 함께 const를 사용하세요.

C 프로그래머들은 일반적으로 더 나은 성능을 위해 구조체를 포인터로 전달하는 것을 선호합니다.

직접 해보기

#include <stdio.h>
#include <string.h>
#include "product.h"

int main() {
    char name[50];
    double price;
    int quantity;
    
    // 입력 읽기
    scanf("%s", name);
    scanf("%lf", &price);
    scanf("%d", &quantity);
    
    // TODO: Product 변수를 생성하고 입력값으로 초기화하세요
    // Hint: strcpy를 사용하여 이름을 구조체의 name 필드에 복사하세요
    
    // TODO: Product를 사용하여 display_by_value를 호출하세요
    
    // TODO: Product에 대한 포인터를 사용하여 display_by_pointer를 호출하세요
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Object Oriented Programming의 모든 레슨