사지방에서 C언어 공부를 하다가 궁금한 점이 하나 생겼다.
#include <stdio.h>
int main(){
int arr[5] = {1, 2, 3, 4, 5};
printf("arr: %p &arr: %p\n", arr, &arr);
return 0;
}
위의 코드는 arr이라는 1차원 정적 배열이 선언됐을 때, arr값과 &arr값을 출력하라는 프로그램을 나타낸다.
필자는 당연히 arr이라는 변수 안에 담긴 값과 arr이라는 변수가 메모리 상에 위치한 주소값이 다르다고 생각했다.
위 코드를 컴파일(ubuntu-18.04 의 gcc compiler로 컴파일 함)해서 프로그램을 실행시켜봤다.
그런데 결과는 다음과 같았다.
arr: 0x7ffd837018a0 &arr: 0x7ffd837018a0
결과는 필자의 예상과 달랐다. 궁금해서 구글링을 해보니 stackoverflow에서 다음과 같은 답을 얻었다.
An array is a block of contiguous objects with no spaces in between.
배열이란 연속적인 objects들 사이에 빈 공간이 없는 하나의 block이라는 말이다.
이를 그림으로 나타내어 이해해보자.
+---------------------+--------------+---------+
| Variable Name | Address | Value |
+---------------------+--------------+---------+
| arr |0x7ffd837018a0| 1 |
| | +---------+
| | | 2 |
| | +---------+
| | | 3 |
| | +---------+
| | | 4 |
| | +---------+
| | | 5 |
+---------------------+-------------+----------+
즉, arr이라는 정적 배열 변수는 5개의 int 값들(1, 2, 3, 4, 5)을 갖고 있고, 메모리 상에서 단 하나의 주소(0x7ffd837018a0)를 갖는 변수이다.
arr을 코드상에서 단독으로 쓴다면 다음과 같은 특별한 규칙이 적용된다.
만약, arr이라는 정적 배열 변수를 단항연산인 엠퍼샌드(&) 연산이나 sizeof 연산에 쓰지 않고, 단독적으로 쓴다면 arr는 배열의 [0]번째 index에 해당하는 member의 주소를 나타낸다.
결국, arr은 int *
타입의 0x7ffd837018a0라는 주소값을 나타낸다.
그렇다면, &arr에서는 어떨까? 이 경우에는 방금 위에서 말한 그 특별한 규칙이 적용되지 않는다.
다른 변수들이 그런 것처럼, &arr은 arr이 메모리 상에 위치한 주소값을 반환한다.
&arr은 int (*)[5]
타입의 0x7ffd837018a0라는 주소값을 반환한다.
이 글은 https://stackoverflow.com/questions/7844049/how-are-c-arrays-represented-in-memory 을 참고하여 만들어졌습니다.
저는 컴퓨터 관련 학과를 3학기만 마치고, 군입대를 한 일개 휴학생이기 때문에, 글의 많은 오류가 있을 수 있습니다. 댓글로 잘못된 설명을 지적해주시면 정말 감사하겠습니다 :)