-
포인터 붕괴와 붕괴가 아닌 것개발/C·C++ 2024. 9. 28. 23:18
int형 2차원 배열을 선언한다.
int buf[100][100];
다음 둘의 주소 값이 같을까?
cout << buf[0] << endl; cout << &buf[0] << endl;
정답. O.
2차원 배열의 첫 번째 행의 시작 주소를 가리킨다.
auto를 이용해서 타입 확인을 해보면 타입이 다르다. 주소값은 같은데 타입이 다르다?
무슨 의미일까.
buf[0]은 사실상 int[100]의 시작 주소이므로 int* 타입으로 붕괴된다.
문제는(?) &buf[0]인데, 이 표현식은 행 전체를 &으로 묶는 효과가 생긴다.
타입은 (int*)[100]이 된다. 100개의 정수 배열에 대한 포인터다.
조금 풀어서 이야기 하보면, buf[0]이 1차원 배열의 시작 주소를 가리키는데 이 앞에 주소 연산을 붙이니 1차원 배열 단위의 주소 연산을 할 수 있게 된다는 거다.
코드로 확인해보자.
auto p1 = &buf[0]; auto p2 = buf[0]; // 메모리 간격 차이는 400바이트 cout << &p1[0] << endl; cout << &p1[1] << endl; // 메모리 간격 차이는 4바이트 cout << &p2[0] << endl; cout << &p2[1] << endl;
p1의 타입은 (int*)[100]이며 앞서 말했듯 100개의 정수 배열의 포인터다. 1차원 배열 단위(정수형 요소 100개) 단위의 포인터 연산을 할 수 있다. 인덱스가 1 증가하면 배열 요소 기준으로 100 간격이 생기며 int형 배열이니까 100 * 4 = 400의 차이가 난다. 실제 주소 값을 출력해보고 윈도우 계산기를 프로그래머용으로 변환해 10진수로 확인해보면 정확히 400 차이를 확인할 수 있다.
p2는 그냥 1차원 배열이니까 4 차이가 난다.
이 차이점을 명확하게 인지하고 사용하자.
'개발 > C·C++' 카테고리의 다른 글
VirtualAlloc()의 메모리 할당에 대해 (0) 2024.10.12 64비트 시스템에서 메모리 정렬 경계에 대해 (0) 2024.10.11 덧셈 연산 어셈블리 코드 간단 분석 (1) 2024.09.07 std::transform()에 대한 간단한 고찰 (2) 2024.09.04 포인터의 타입 추론 (0) 2024.08.31