역사적으로 포인터는 C 언어에서 메모리 작업의 기초가 되었으며, 배열 요소 및 동적 구조체에 대한 효율적인 접근을 위한 유연한 메커니즘을 제공합니다. 그러나 배열에 대한 포인터와 포인터 배열의 문법과 의미는 종종 혼란을 일으킵니다.
문제: 초보 프로그래머는 종종 배열에 대한 포인터 (pointer to array)와 포인터 배열 (array of pointers)를 혼동하여 잘못된 메모리 사용, 파라미터 전달 오류 및 해석하기 어려운 문법 오류를 초래합니다.
해결책:
선언 및 사용 예:
// 10개의 int 배열에 대한 포인터: int (*p)[10]; int arr[10]; p = &arr; // 10개의 int에 대한 포인터 배열 int *ap[10]; for (int i = 0; i < 10; ++i) { ap[i] = &arr[i]; } // 배열에 대한 포인터로 요소에 접근하기: (*p)[2] = 5; // arr의 세 번째 요소 // 포인터 배열을 사용하여 값 얻기: *ap[2] = 8; // ap를 통해 arr의 세 번째 요소
주요 특징:
**int p[10]와 int (p)[10]은 동일합니까?
아니요. int *p[10]은 int에 대한 10개의 포인터로 구성된 배열입니다. int (*p)[10]은 10개의 int로 구성된 배열에 대한 포인터입니다. 괄호 없이 혼란이 생깁니다!
코드 예:
int arr[10]; int *p[10]; // 포인터 배열 int (*q)[10] = &arr; // 배열에 대한 포인터
*일반 int 포인터를 int (p)[10]형 변수에 자유롭게 할당할 수 있습니까?
아니요. 일반 int *는 하나의 요소를 가리키고, int (*p)[10]은 10개의 정수 배열을 가리키기 때문에 타입이 호환되지 않습니다.
2차원 배열을 함수에 올바르게 전달하는 방법은 무엇입니까?
두 번째 차원의 크기를 명시적으로 지정해야 합니다:
void foo(int a[][4], int n); // n개의 4요소 행 배열
또는 배열에 대한 포인터를 사용할 수 있습니다:
void bar(int (*a)[4], int n);
엔지니어가 변수를 int *p[10]으로 선언하고, &arr을 할당하려고 시도하며, arr이 int arr[10]인 경우 배열처럼 접근하려고 하면 컴파일 오류나 잘못된 동작이 발생합니다.
장점:
단점:
개발자가 괄호를 주의 깊게 사용하고 int (*p)[10]을 사용하여 차이를 명확히 이해하며, 배열을 함수에 올바르게 전달하고 typedef를 사용하여 선언을 간소화합니다.
장점:
단점: