[C] array name의 주소와 array의 첫번째 원소의 주소

yourmemory의 이미지


친구에게 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 표준에 나와있다면 어떤 부분인지 궁금합니다.

익명사용자의 이미지

배열의 경우에는 컴파일러가 &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])

입니다.

yourmemory의 이미지

답변감사합니다.^^

질문이 있는데요,

"그 이유는 배열의 경우에는 포인터와 동등하게 사용할 수 있게 하기 위해서 a만 써도 &a로 역할을 해야 하기 때문입니다."

이 부분에서 배열의 경우에 포인터와 동등하게 사용할 수 있게 하기 위해서 필요한 것이

a == &a인가요?

a == &a[0]만으로도 충분하지 않은건가요?

익명사용자의 이미지

아.. 저도 답글 달다가 착각했군요. a == &a[0]죠. 그런데 a라는 변수는 실제 메모리 주소에서 a라는 배열의 시작점 위치에 해당합니다. 따라서 이 변수의 주소를 &a로 구하면 다시 변수 a의 시작점 위치가 반환됩니다. 즉, &a[0] == &a가 되는 것이죠.

winner의 이미지

변경되지 않는 것은 int 가 아니라 int * 이니까요.

배열과 pointer 는 가장 C 에서 골때리는 문제이긴 한데
배열에 적용되는 연산은 두가지라고 합니다.
sizeof 와 배열 첫 원소의 주소값을 취하는 것이죠.

두번째의 연산이 pointer 와 배열이 헷갈리는 이유를 만들죠.

배열의 주소가 배열 첫 원소의 주소가 되는 것은 역시 참입니다만(low level 관점에서)
논리적으로 두 type 은 다르며 따라서 동일하게 취급하는 것은 잘못되었다고 합니다.

전웅의 이미지

3가지가 문제군요.

1. 배열은 상수 포인터이다.

배열, 포인터 관계를 설명하기 위해서 자주 도입해 사용되는 개념입니다만
결코 추천하지 않습니다. 배열, 포인터 혼란의 적지 않은 원인이 바로 이런
설명에서 기인합니다. 예전에는 뉴스그룹에서 포인터 상수니, 상수
포인터니 말 바꿔가며 어느 것이 설명에 더 나은 개념이나 토론도 하고
했습니다만 결론은 아예 배열과 포인터를 확실히 구분하고 이 둘 사이의
변환을 올바르게 이해하자는 것이었습니다. 상수 포인터(const T *)든,
포인터 상수(T * const)든 개념상 결국 포인터이지 배열은 아니라는 것
이었습니다. 뭐, 어찌되었든 학습자가 "올바른" 내용을 가장 쉽게 익힐 수
있는 방법이 있다면 그것이 최선의 방법이 아닐까 생각합니다.

2. 배열의 주소와 배열 첫 원소의 주소 문제

이것도 많은 분들이 혼동하시는 문제 중 하나입니다. 어린이들이 소꼽놀이를
하고 있습니다. 바닥에 분필로 집 모양의 선을 그려놓고 방도 나누었습니다.
그 중 북쪽벽에 있는 방이 철수방이 되었습니다. 그 순간(!) 어떤 아저씨가
GPS 수신기를 들고 아이들 곁으로 다가왔습니다 (대체 무슨... --;).
그리고는 아이들이 만든 가상의 집 북쪽 위치를 측정했습니다. 북위 38.12도
(헉!!)가 나오네요. 그래서 이번엔 철수방의 위치를 측정했습니다. 역시
북위 38.12도(다시 헉!!)가 나오네요 (당연히 그럴 수 밖에...). 그럼 철수,
영희, 말순이가 사는 집의 위치와 철수방의 위치가 같으니
"철영말이네 집 = 철수 방" 인가요?

배열과 그 배열 첫 요소의 주소는 같지만, 주소가 같다고 해서 동일한 개념
의 존재가 아닙니다. 둘은 분명히 다른 type 과 다른 특성을 가지고
있습니다. 일례로,

int (*x)[10] = &a;
int *y = &a[0];
 
if ((void *)x == (void *)y)
    result = (sizeof(*x) == sizeof(*y));

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

yourmemory의 이미지

오랜만에 이 글을 다시 찾아보았는데,

좋은 답글이 달려있네요.

너무 감사합니다. 꾸벅. ^^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.