프로그래밍시스템 프로그래머

C 언어에서 함수의 매개변수를 전달하는 메커니즘인 값에 의한 전달과 포인터에 의한 전달에 대해 자세히 설명해 주실 수 있나요? 각 접근 방법의 사용이 정당화되는 경우의 예를 들어 주세요.

Hintsage AI 어시스턴트로 면접 통과

답변.

C 언어에서는 매개변수가 항상 값에 의해 전달됩니다. 즉 호출 코드의 값 복사본이 함수에 전달됩니다. 함수 외부의 변수 값을 변경해야 하는 경우 포인터에 의한 전달을 사용합니다.

값에 의한 전달

스칼라(예: int)를 전달할 때 함수는 자신의 복사본을 받습니다:

void foo(int a) { a = 10; } int main() { int x = 5; foo(x); // x == 5, 변경되지 않음! }

포인터에 의한 전달

변수 값을 변경하기 위해 포인터를 사용합니다:

void foo(int* a) { *a = 10; } int main() { int x = 5; foo(&x); // x == 10, 값이 변경됨! }

포인터 사용 시기

  • 여러 값을 반환해야 할 때.
  • 큰 구조체를 변경해야 할 때 (시간과 메모리를 절약, 복사 없음).
  • 배열과 작업할 때 (항상 포인터로 전달됨).

속임수 질문.

배열이 함수의 매개변수로 참조에 의해 전달되는가?

많은 사람들이 "참조에 의해"라고 대답하지만 C에서는 함수 서명에서 배열이 참조에 의해 전달될 수 없으며 사실상 포인터로 전환됩니다.

올바른 답변:

배열이 함수에 전달될 때 실제로는 그 첫 번째 요소에 대한 포인터가 전달됩니다. 즉 호출 함수는 배열의 실제 크기를 알지 못하며 배열 요소의 모든 변경은 원래 배열에 반영됩니다.

void foo(int arr[]) { arr[0] = 100; } int main() { int a[3] = {1,2,3}; foo(a); // a[0]은 100이 됨! }

역사


하나의 프로젝트에서 함수가 int arr[10]으로 선언된 배열의 값을 업데이트했지만 호출 코드에서 배열은 더 작은 크기였습니다. 함수가 실제 크기를 알지 못했기 때문에 버퍼 오버플로우와 메모리 손상이 발생했습니다.


또 다른 경우에 값에 의해 구조체를 함수에 전달함으로써 큰 메모리 블록이 여러 번 복사되어 애플리케이션 성능이 저하되었습니다.


개발자는 스칼라를 "참조"에 의해(포인터를 통해) 전달하면 원래 값이 변경되지 않기를 기대했지만 포인터 산술의 오류로 인해 가시 영역 외부의 메모리를 변경하여 예측할 수 없는 결과를 초래했습니다.