프로그래밍C 개발자

C 언어에서 함수에 배열을 전달하는 메커니즘에 대해 자세히 설명하십시오. 이 모델과 관련된 위험은 무엇이며 함수 내에서 배열을 안전하게 작업하기 위해 올바르게 구성하는 방법은 무엇입니까?

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

답변

C 언어에서 배열은 값에 의해 함수에 전달되지 않습니다. 배열을 인수로 전달하면 실제로 배열의 첫 번째 요소에 대한 포인터가 함수에 전달됩니다. 이는 함수가 배열의 복사본이 아닌 원래 배열을 수정하게 됩니다.

예:

void fillArray(int arr[], int n) { for (int i = 0; i < n; ++i) arr[i] = i*i; } int main() { int myarr[5]; fillArray(myarr, 5); // ok }

함수 내에서:

  • sizeof(arr)를 통해 원래 배열의 크기를 알 수 없습니다 — 이는 포인터의 크기를 반환합니다, 배열의 크기가 아닙니다.
  • 명시적으로 전달한 크기의 메모리 조각만 작업할 수 있습니다.

배열을 올바르고 안전하게 작업하려면 다음과 같이 하십시오:

  • 항상 배열의 크기를 별도의 인수로 명시적으로 전달하십시오;
  • 크기에 대해 상수 또는 매크로 래퍼를 사용하십시오;
  • 배열의 변경을 방지하려면 const int *arr를 전달하십시오.

트릭 질문

질문: int arr[] 인수로 전달된 원래 배열의 크기를 함수 내부에서 sizeof(arr)로 알 수 있습니까?

답변: 아닙니다, 알 수 없습니다! 함수 내부에서 sizeof(arr)는 타입에 대한 포인터의 크기를 반환하며 (예: 4 또는 8 바이트), 배열의 크기를 반환하지 않습니다.

예:

void f(int arr[]) { printf("%zu ", sizeof(arr)); // 포인터의 크기, 배열이 아님! } int main() { int x[10]; f(x); // 일반적으로 8(x86_64) 또는 4(x86)를 출력합니다 }

실제 오류 사례


이야기

상업 프로젝트에서 배열 복사 함수를 작성할 때 배열 크기를 함수 내부에서 sizeof(arr)/sizeof(int)을 사용하여 동적으로 계산하려고 했습니다. 결과적으로 크기 계산이 항상 1(8/8)로 되어 배열의 일부분만 복사되었고 이는 예측할 수 없는 방식으로 데이터를 덮어쓰게 되었습니다.


이야기

하나의 네트워크 애플리케이션에서 데이터 전송 함수가 배열 형태의 버퍼를 인수로 받았지만 그 크기를 명시적으로 지정하지 않아, 전체 버퍼가 전송되지 않거나 배열 경계를 넘어 잡음 데이터를 읽는 문제가 발생하여 전송 오류 및 연결 불안정이 초래되었습니다.


이야기

이미지 작업을 위한 라이브러리를 작성할 때 프로그래머가 이미지 배열을 칠하는 함수에 배열 크기를 필수 매개변수로 제공하지 않았습니다. 그 결과, 특정 입력에서 버퍼 오버플로우가 발생하고 프로그램이 크래시되었으며, 이는 대형 이미지에 대한 통합 테스트에서만 발견되었습니다.