역참조 연산자 *와 주소 연산자 &는 C에서 메모리 작업의 근본적인 도구 중 하나입니다. 이들은 메모리 내 데이터를 직접 관리할 수 있게 해주며, 그 덕분에 C는 시스템 프로그래밍을 위한 인기 있는 언어가 되었습니다.
문제의 역사:
C 언어가 등장한 이래(1970년대), 그의 철학은 메모리의 저수준 관리와 밀접하게 연관되어 있었습니다. 연산자 *와 &는 CPU 레벨에서 사용되는 간접 주소 지정 기법을 구현하여, 포인터와 함께 작업하고, 동적으로 메모리를 할당하며, 효율적인 데이터 구조를 생성할 수 있도록 해줍니다.
문제: 이 연산자 사용의 오류는 메모리 누수, 데이터 손상, 세그멘테이션 폴트와 같은 수많은 버그를 초래할 수 있습니다. 컴파일러는 이러한 오류를 항상 명확하게 신호하지 않으며, 특히 포인터의 크기가 일치하지만 내용이 다른 경우에 더욱 그러합니다.
해결책: 포인터 유형에 주의하고, 할당된 메모리의 생명 주기를 추적하며, 초기화 및 적절한 해제를 수행하고, 역참조 연산 및 사용된 주소의 적합성을 확인해야 합니다.
코드 예:
int x = 10; int *p = &x; // 주소 가져오기 int y = *p; // 역참조 (주소의 값 가져오기) // 배열에 대한 포인터 작업 int arr[3] = {1,2,3}; int *pa = arr; printf("%d", *(pa+1)); // 배열의 두 번째 요소
주요 특징:
임시 변수의 주소를 가져올 수 있나요, 예: & (x + y)?
아니요, 표현식의 주소는 가져올 수 없습니다, 표현식의 결과는 메모리 객체가 아니기 때문입니다. 주소는 변수, 배열이나 구조체에서만 가져올 수 있습니다.
코드 예:
int z = 5; int p = &(z + 1); // 컴파일 오류
void 포인터의 역참조는 어떻게 다릅니까?
void * 타입 포인터는 특정 타입으로 캐스팅하기 전에는 직접적으로 역참조할 수 없습니다. 이것은 범용 포인터이지만, 역참조 작업은 명시적 캐스팅 후에만 타입 독립적입니다:
void *pv = &x; int value = *(int*)pv; // 괜찮음
널 포인터(NULL)를 역참조할 수 있나요?
아니요, 이는 미정의 동작을 초래합니다 — 메모리 파괴 또는 서버 크래시. 역참조하기 전에 항상 포인터를 확인하십시오:
int *ptr = NULL; if (ptr) { *ptr = 10; // 절대 실행되지 않음 }
개발자는 함수 내에서 로컬 변수의 주소를 가져와 호출 코드에서 역참조합니다.
장점:
단점:
변수에 대한 동적 메모리 할당이 이루어지고, 주소는 호출 코드로 반환되며 마지막에 free를 통해 해제됩니다.
장점:
단점: