프로그래밍C 개발자

C 언어에서 포인터와 배열을 함수에 전달할 때 어떤 일이 발생합니까? 어떤 차이점이 있으며, 함정은 무엇이고 전형적인 오류를 피하는 방법은 무엇입니까?

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

답변.

C 언어에서 포인터나 배열을 함수에 전달할 때 사실상 포인터의 값 복사(즉, 메모리 주소)가 전달되며, 실제 배열이나 메모리 내용이 전달되는 것은 아닙니다. 역사적으로 C의 배열은 값으로 전달되지 않으며, 대신 배열의 첫 번째 요소에 대한 포인터가 함수로 전달됩니다. 이 메커니즘은 메모리를 절약하지만 잘못 사용할 경우 원치 않는 부작용을 초래할 수 있습니다.

문제 — 포인터와 배열 간의 혼동: 개발자들은 종종 함수 안에서 배열을 통해 외부 배열을 변경할 수 없거나 함수가 자동으로 전달된 배열의 크기를 알 수 있다고 생각합니다. 실제로 함수는 원래 배열의 크기를 잃고 쉽게 그 경계를 넘어설 수 있습니다.

해결책 — 항상 배열의 크기를 별도의 인자로 명시적으로 전달하고, 포인터의 복사와 객체의 복사 간의 차이를 명확히 이해하며, 포인터를 통해 이루어진 모든 변경이 원본 데이터에 반영됨을 잊지 말아야 합니다.

배열을 올바르게 전달하는 예:

void print_array(const int* arr, size_t size) { for (size_t i = 0; i < size; ++i) printf("%d ", arr[i]); } int main() { int nums[] = {1,2,3,4,5}; print_array(nums, sizeof(nums)/sizeof(nums[0])); return 0; }

주요 특징:

  • 함수에는 배열의 주소가 전달되며, 요소의 복사가 이루어지지 않습니다.
  • 배열의 크기는 명시적으로 전달해야 합니다.
  • 함수 내에서 요소를 변경하면 외부 배열도 변경됩니다.

함정 질문.

함수가 int arr[10]으로 선언된 전달된 배열의 길이를 알 수 있습니까?

답변: 아니요, 함수 안에서 sizeof(arr) 표현식은 포인터의 크기를 반환하고 전체 배열의 크기는 반환하지 않습니다. 크기는 별도로 전달해야 합니다.

함수에서 배열을 int arr[]와 int arr로 전달하는 것은 동일합니까?*

답변: 예, 함수의 시그니처에서 둘은 동등하며, 두 경우 모두 int에 대한 포인터가 전달됩니다. 차이는 문법에만 있습니다.

함수 내에서 배열의 요소를 변경하면 원본 배열이 변경됩니까?

답변: 예, 포인터가 전달되었기 때문에 함수는 포인터가 가리키는 메모리를 변경합니다.

전형적인 오류 및 안티 패턴

  • 배열의 크기를 인자로 전달하지 않기 (경계를 넘어서는 경우).
  • 함수 내에서 배열의 크기를 sizeof(arr)로 결정하기 (잘못된 결과).
  • 다양한 문맥에서 int arr[10]과 int* arr을 혼동하기.

실생활의 예

부정적 경우

프로젝트가 배열 초기화 함수를 구현할 때 배열 크기를 함수 내부에서 sizeof(arr) / sizeof(arr[0])로 정의했습니다. 테스트 단계에서 함수는 작동했지만 다른 배열을 처리할 때 외부 메모리를 덮어쓰거나 올바르게 작동하지 않았습니다.

장점:

  • 함수 시그니처가 단순해졌습니다.

단점:

  • 다른 데이터로 인해 프로그램이 중단되거나 잘못 작동했습니다.

긍정적 경우

함수는 항상 배열 크기를 개별 매개변수로 받아, 길이는 호출하는 쪽에서 계산했습니다. 함수 내부에서는 전달된 매개변수로만 작업했습니다.

장점:

  • 경계를 넘어서는 일이 없음을 보장합니다.
  • 더 신뢰할 수 있고 안전하며 이식 가능한 코드입니다.

단점:

  • 크기를 명시적으로 전달해야 하며, 호출이 다소 길어집니다.