포인터 산술은 C 언어의 기본적인 특징으로, 메모리 작업을 유연하게 하지만 잠재적으로 위험하게 만듭니다.
포인터 산술은 저수준 언어의 특성으로 인해 발생했으며, 배열 작업 및 메모리에서 구조화된 데이터를 직접 처리하기 위해 설계되었습니다. C 언어의 모든 포인터는 가리키고 있는 타입의 크기를 "알고" 있습니다.
많은 개발자들은 포인터에 1을 더하면 주소가 정확히 1바이트 증가할 것이라고 착각합니다. 사실 증가하는 양은 sizeof(타입)에 따라 다릅니다. 특히 크기가 다른 구조체와 같은 다양한 데이터 타입으로 작업할 때 메모리로의 이동에서 쉽게 실수할 수 있습니다. 또한 void*와의 포인터 산술은 허용되지 않으며, 이는 표준적인 오류입니다.
모든 포인터와 관련된 산술 연산은 해당 타입의 크기를 고려하여 진행되므로 배열 작업을 최대한 효율적으로 수행할 수 있습니다. 예를 들어:
#include <stdio.h> int arr[4] = {10, 20, 30, 40}; int *p = arr; printf("%d\n", *(p + 2)); // 30을 출력
여기서 (p + 2)는 포인터를 2 * sizeof(int) 바이트 앞으로 이동시키는 것이지 단순히 2 바이트를 이동하는 것이 아닙니다.
주요 특징:
void 포인터에 대해 증가/감소 연산을 수행할 수 있습니까?
아니요, C 표준은 void에 대한 산술을 금지합니다. 먼저 포인터를 구체적인 타입으로 캐스팅해야 하며, 예를 들어 (char)로 변환한 후 산술을 수행해야 합니다.
void *vp = arr; char *cp = (char *)vp; cp++;
구조체나 배열에 대한 포인터에 배열 크기를 초과하는 값을 더하면 어떻게 됩니까?
이는 허용된 메모리 영역을 넘어서는(정의되지 않은 동작) 결과를 초래합니다. C는 배열의 경계를 확인하지 않으며, 이는 프로그래머의 책임입니다.
두 포인터를 직접 더할 수 있습니까?
아니요, 포인터의 더하기는 금지되어 있으며 의미가 없습니다. 동일한 배열에 속하는 두 포인터의 뺄셈만 허용됩니다.
젊은 개발자가 int 배열을 포인터로 작업하면서 타입 크기를 잊고 고정된 바이트 수만큼 포인터를 이동시켰습니다.
장점:
단점:
경험 많은 개발자는 항상 (ptr + n)과 같은 표현을 사용하여 컴파일러가 타입 크기에 따라 이동을 스케일링하도록 신뢰합니다.
장점:
단점: