프로그래밍C 개발자

C 언어에서 함수에 매개변수가 전달되는 메커니즘은 어떻게 작동하나요? 서로 다른 유형, 구조체 및 배열의 변수를 전달할 때 유형 오류를 피하려면 어떻게 해야 하나요?

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

답변.

C 언어에서 함수에 전달되는 매개변수는 항상 값에 의해 전달됩니다. 이는 함수가 매개변수의 값의 복사본을 받는다는 것을 의미합니다. 간단한 유형(int, float)의 경우 이는 명백합니다: 함수 내의 변경사항은 원래 변수를 변경하지 않습니다. 배열과 구조체에는 몇 가지 뉘앙스가 있습니다:

  • 배열을 함수에 전달할 때는 사실상 첫 번째 요소에 대한 포인터가 전달되고, 전체 배열은 전달되지 않습니다. 그러나 포인터 자체는 여전히 값으로 전달됩니다.
  • 구조체는 명시적으로 복사본(값으로)을 전달할 수 있지만, 포인터를 통해 복사본을 만드는 것이 더 유리합니다 — 그렇게 하면 함수가 원래 구조체를 수정할 수 있습니다.

예시: 배열과 구조체 처리

#include <stdio.h> typedef struct { int a; int b; } Pair; void modifyArray(int arr[], int size) { arr[0] = 42; // 원래 배열 수정 } void modifyStruct(Pair s) { s.a = 100; // 로컬 복사본만 변경 } void modifyStructPtr(Pair *s) { s->a = 200; // 포인터를 통해 원본 변경 } int main() { int nums[2] = {1, 2}; Pair p = {10, 20}; modifyArray(nums, 2); modifyStruct(p); modifyStructPtr(&p); printf("nums[0]=%d, p.a=%d\n", nums[0], p.a); // nums[0]=42, p.a=200 return 0; }

함정 질문.

질문: 함수가 void func(int arr[10])로 선언되면, 함수 내부에서 이 배열이 항상 10개의 요소를 가지나요?

답변: 아니요. 매개변수로 int arr[10]라고 쓴 것은 사실 int *arr와 동일합니다 — 배열의 크기가 전달될 때 사라집니다. 함수는 배열의 실제 길이를 알지 못하므로 항상 길이를 함께 전달하는 추가 매개변수를 사용해야 합니다. 그렇지 않으면 배열의 경계를 넘는 접근 및 UB가 발생할 수 있습니다.

예시:

void foo(int arr[10]) { printf("%d\n", arr[9]); // arr가 꼭 10개의 요소를 포함하는 것은 아닙니다! }

역사

신호 처리 프로젝트에서 배열을 함수에 전달했으며, 길이가 항상 동일하다고 가정했지만, 한 경우에 더 작은 배열을 전달했습니다. 결과 — 메모리 경계를 넘어 접근하고 응용 프로그램이 충돌하며 컨트롤러에서 예측할 수 없는 동작이 발생했습니다.


역사

은행 소프트웨어에서 구조체를 값으로 전달하여 수정하려고 했지만 포인터로 전달하지 않았습니다. 변경 사항이 유지되지 않아 처리 모듈이 계좌의 상태를 업데이트하지 않아 계산에 오류가 발생했습니다.


역사

텔레메트리 시스템에서 학생이 배열을 정리하는 함수를 추가했지만 길이를 전달하는 것을 잊었고, 배열의 크기가 서로 다르었습니다. 오류는 대량의 잘못된 데이터를 수집하고 버그를 찾는 데 오랜 시간이 지난 후에야 발견되었습니다.