[C] array name의 주소와 array의 첫번째 원소의 주소
글쓴이: yourmemory / 작성시간: 목, 2006/11/30 - 9:33오전
친구에게 C 언어에 대해서 간략하게 설명해주고 있었는데요,
"array와 pointer가 실제로는 동일한 역할을 한다."는 이야기를 설명하면서
array name은 const pointer라는 설명을 했습니다.
그래서 마치,
int a[10];은
const int *a' = malloc(sizeof(int) * 10)과 같은 이치이다. 라는 식으로 설명하였는데요.
(1. 물론, 할당되는 위치가 다르겠지만요... 2. a'와 같은 identifier는 안되는 것도 이야기했습니다. 단지 설명을 위해...)
[질문]
위에서 a[0] 이 0x00010000에 위치한다면, a가 바로 이 위치를 나타내는 pointer이고 a값도 0x00010000 입니다.
즉, a == &a[0].
여기까지는 잘 설명했는데, 친구가 갑자기 이렇게 물어보는겁니다.
"그럼 a의 주소는 모야?" <- &a
그래서 그냥 "어 그건 따로 주소가 정해지는거겠지..." 이렇게 얼버무리고 집에 와서 gcc로 해보았는데
신기하게도 &a == a == &a[0] 이렇게 되더군요.
혹시 왜 이렇게 되는지,
그 이유에 해당하는 것이 C99 표준에 나와있다면 어떤 부분인지 궁금합니다.
Forums:
배열의 경우에는
배열의 경우에는 컴파일러가 &a == a로 해석해 줍니다. 그 이유는 배열의 경우에는 포인터와 동등하게 사용할 수 있게 하기 위해서 a만 써도 &a로 역할을 해야 하기 때문입니다. (실제로 위의 예에서 a가 지역 변수라면 a는 stack상에 크기 10인 배열로 할당됩니다.) 그러나 포인터의 경우 &a != a입니다. 위의 예처럼 int *a로 선언해 두고 malloc으로 할당할 경우 int *a라는 변수의 주소는 stack 상에 존재하게 되고 a에 저장된 주소 값은 heap에서 할당된 주소가 됩니다. 따라서 &a는 stack에 있는 a라는 변수의 주소가 되고 a는 heap에서 나타나는 주소가 됩니다.
즉,
배열의 경우 &a == a == &a[0]
포인터의 경우 &a != (a == &a[0])
입니다.
re
답변감사합니다.^^
질문이 있는데요,
"그 이유는 배열의 경우에는 포인터와 동등하게 사용할 수 있게 하기 위해서 a만 써도 &a로 역할을 해야 하기 때문입니다."
이 부분에서 배열의 경우에 포인터와 동등하게 사용할 수 있게 하기 위해서 필요한 것이
a == &a인가요?
a == &a[0]만으로도 충분하지 않은건가요?
아.. 저도 답글
아.. 저도 답글 달다가 착각했군요. a == &a[0]죠. 그런데 a라는 변수는 실제 메모리 주소에서 a라는 배열의 시작점 위치에 해당합니다. 따라서 이 변수의 주소를 &a로 구하면 다시 변수 a의 시작점 위치가 반환됩니다. 즉, &a[0] == &a가 되는 것이죠.
통상 const int * 로 생각하지 않고 int * const 라고 생각합니다.
변경되지 않는 것은 int 가 아니라 int * 이니까요.
배열과 pointer 는 가장 C 에서 골때리는 문제이긴 한데
배열에 적용되는 연산은 두가지라고 합니다.
sizeof 와 배열 첫 원소의 주소값을 취하는 것이죠.
두번째의 연산이 pointer 와 배열이 헷갈리는 이유를 만들죠.
배열의 주소가 배열 첫 원소의 주소가 되는 것은 역시 참입니다만(low level 관점에서)
논리적으로 두 type 은 다르며 따라서 동일하게 취급하는 것은 잘못되었다고 합니다.
3가지가 문제군요. 1.
3가지가 문제군요.
1. 배열은 상수 포인터이다.
배열, 포인터 관계를 설명하기 위해서 자주 도입해 사용되는 개념입니다만
결코 추천하지 않습니다. 배열, 포인터 혼란의 적지 않은 원인이 바로 이런
설명에서 기인합니다. 예전에는 뉴스그룹에서 포인터 상수니, 상수
포인터니 말 바꿔가며 어느 것이 설명에 더 나은 개념이나 토론도 하고
했습니다만 결론은 아예 배열과 포인터를 확실히 구분하고 이 둘 사이의
변환을 올바르게 이해하자는 것이었습니다. 상수 포인터(const T *)든,
포인터 상수(T * const)든 개념상 결국 포인터이지 배열은 아니라는 것
이었습니다. 뭐, 어찌되었든 학습자가 "올바른" 내용을 가장 쉽게 익힐 수
있는 방법이 있다면 그것이 최선의 방법이 아닐까 생각합니다.
2. 배열의 주소와 배열 첫 원소의 주소 문제
이것도 많은 분들이 혼동하시는 문제 중 하나입니다. 어린이들이 소꼽놀이를
하고 있습니다. 바닥에 분필로 집 모양의 선을 그려놓고 방도 나누었습니다.
그 중 북쪽벽에 있는 방이 철수방이 되었습니다. 그 순간(!) 어떤 아저씨가
GPS 수신기를 들고 아이들 곁으로 다가왔습니다 (대체 무슨... --;).
그리고는 아이들이 만든 가상의 집 북쪽 위치를 측정했습니다. 북위 38.12도
(헉!!)가 나오네요. 그래서 이번엔 철수방의 위치를 측정했습니다. 역시
북위 38.12도(다시 헉!!)가 나오네요 (당연히 그럴 수 밖에...). 그럼 철수,
영희, 말순이가 사는 집의 위치와 철수방의 위치가 같으니
"철영말이네 집 = 철수 방" 인가요?
배열과 그 배열 첫 요소의 주소는 같지만, 주소가 같다고 해서 동일한 개념
의 존재가 아닙니다. 둘은 분명히 다른 type 과 다른 특성을 가지고
있습니다. 일례로,
result 의 결과는 무엇일까요?
3. 배열이 포인터로 변환되는 문맥
이 모든 혼란의 원인은 C 언어의 조상에서 유래합니다. C 언어에서 배열에
직접 적용될 수 있는 연산은
- sizeof 적용
- & 연산자 적용
- 문자 배열 초기화에 사용
뿐입니다. 그 외에는 첫 요소를 가리키는 포인터로 "변신"을 하는 것
뿐입니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
답변 감사합니다.
오랜만에 이 글을 다시 찾아보았는데,
좋은 답글이 달려있네요.
너무 감사합니다. 꾸벅. ^^
댓글 달기