포인터 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를 사용하고, 수정해야 할 때는 일반 포인터를 사용하세요. 효율성과 명확한 의도를 모두 얻을 수 있습니다.
챌린지
쉬움구조체를 값으로 전달하는 것과 포인터로 전달하는 것의 차이를 보여주는 Product 모듈을 만들어 보겠습니다. 전체 구조체를 복사본으로 받는 함수와 구조체에 대한 포인터만 받는 함수, 이렇게 두 개의 출력 함수를 작성하게 됩니다.
세 개의 파일을 생성해야 합니다:
product.h: 세 개의 멤버char name[50],double price,int quantity를 가진Product구조체를 선언합니다. 또한 다음 두 함수를 선언합니다:display_by_value—Product를 값으로 전달받아 정보를 출력합니다.display_by_pointer—const 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;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.