해결된 질문
작성
·
514
0
int a = 4;
float b = 4.0f;
double c = 5.0;
int *ptr_a = &a;
float *ptr_b = &b;
double *ptr_c = &c;
Q1. 포인터 변수(ptr_a
)가 변수(a
)에 대하여 저장하는 첫 번째 주소
란, 그 변수(a
)가 memory에 저장될 때, 가장 마지막에 저장되는 1 byte 메모리 공간의 주소를 의미하는 것이 맞나요?
Stack memory에 data가 저장될 때에는 High address로부터 Low address방향으로 저장된다고 알고 있습니다.
포인터는, 변수가 접근하는 메모리 공간의 첫 번째 주소를 저장하는데, 여기서 Memory를 살펴본 바, 첫 번째 주소란, 변수(a)가 stack에 저장될 때, 마지막으로 저장된 1 byte 메모리 공간으로 이해됩니다.
그리고가장 먼저 저장된 변수인 a
의 주소는 b
, c
보다 높은 주소에 위치하고,b
의 주소는 c
보다 높은 주소에 있습니다.
그렇다면, 변수(a)의 4 byte짜리 메모리 공간들에 대해서도 저장될 때, 가장 먼저 저장되는 메모리 공간은 나머지에 비해 높은 주소에 위치한다고 추론할 수 있습니다.
그러므로 포인터가 저장하고 있는 주소값, 즉 그 변수(a
)의 첫 번째 주소란, 가장 마지막에 저장되는 1 byte 크기의 메모리 공간이라고 이해하고 있습니다.
Q2. x64
에서 debugging을 실행할 때, 가장 나중에 저장되는 변수가 가장 높은 주소를 가지고 있는데, 왜 그렇습니까?
x86으로 실행했을 때와 마찬가지로, stack에 쌓이는 메모리 공간들의 주소는 from high to low이어야 한다고 알고 있습니다.
x64로 디버깅을 해보니, 먼저 저장되는 변수 자체의 메모리 공간이 저장되는 순서는 high to low 순으로 주소를 가지지만, 각 변수의 첫 번째 주소를 참고해보면, 이상한 점이 있습니다.
가장 마지막에 저장된 변수 c
가 가장 높은 주소값을 가지고 있다는 것입니다.
stack에 저장되는 메모리들의 주소는 가장 높은 메모리 주소부터 낮은 메모리 주소의 방향으로 저장되는데, 여기서는 x86 환경에서 memory 확인했을 때와 달리 정반대입니다.
왜 그럴까요?
답변 2
1
2022. 06. 20.
혹시 다른 분들도 헷갈리시거나 그러실까봐 배운 것을 활용해서 자문자답해봅니다. :)
Q1. 포인터 변수(ptr_a
)가 변수(a
)에 대하여 저장하는 첫 번째 주소
란, 그 변수(a
)가 memory에 저장될 때, 가장 마지막에 저장되는 1 byte 메모리 공간의 주소를 의미하는 것이 맞나요?
아니다. pointer가 저장하는 memory address는, 변수 a
의 first address를 의미한다.
그렇다면, a
의 first address는 무엇일까?
Little Endian인 x86 intel CPU architecture에서는 Low address에 있는 data가 Least Significant Byte에 저장된다. (bit-value 역시 least significant bit에서부터 저장된다.)
아래의 스크린 샷에서 a
는 4 byte
의 size를 가진다.
그러므로, byte order를 나타내자면, [MSB] 00 00 00 04
[LSB]가 된다.
little endian인 현재의 computer에서 data가 저장되는 순서는, low address에 있는 byte data가 먼저 저장되므로, 0x004ffbc0
이 가리키는 memory space 04
가 먼저 저장되었다.
그러므로 pointer ptr_a
가 저장하는 a의 first address
는 가장 먼저 저장된 공간을 의미한다.
(질문 내용 중)
그리고가장 먼저 저장된 변수인 a
의 주소는 b
, c
보다 높은 주소에 위치하고,b
의 주소는 c
보다 높은 주소에 있습니다.
그렇다면, 변수(a)의 4 byte짜리 메모리 공간들에 대해서도 저장될 때, 가장 먼저 저장되는 메모리 공간은 나머지에 비해 높은 주소에 위치한다고 추론할 수 있습니다.
Data가 어떤 memory block에 저장될 때는 little endian방식으로 저장되었다.
[MSB] 00 00 00 04 [LSB]
'04'가 low address인 byte이므로 먼저 저장된 것이다.
그렇게 저장된 data object의 memory address는 Linux OS / GCC Compiler 기준으로 stack에 할당될 때, memory address가 high to low의 방향성을 가지게 된다.
즉 먼저 저장된 변수a가 나중에 저장된 포인터 변수 ptr_a보다, high address를 가진다는 것이다.
하지만 이 방향성이 변수 a에 대하여, 'high address에 있는 '00'이 먼저 저장된다'는 것을 의미하지는 않는다. Data를 저장하는 방식인 endianness와 memory layout에서 address의 방향성을 혼동하지 말자.
Q2. x64
에서 debugging을 실행할 때, 가장 나중에 저장되는 변수가 가장 높은 주소를 가지고 있는데, 왜 그렇습니까?
(홍정모 교수님 말씀대로, OS / Compiler 에 따라 다르기 때문이다.
Stack과 Heap에, data들이 memory를 할당받을 때, 그 address의 방향성이 다르다.
이 variable들은 모두 stack에 allocation된다.
Linux OS / GCC 기준으로 from high to low address의 방향성에 따라 할당될 것이다.
그렇다면,
[High Address Memory]a, b, c, ptr_a, ptr_b, ptr_c
[Low Address Memory]
인 방향성을 보일 것이다.
Linux OS계열인 Ubuntu OS / Clang Compiler를 활용하는 Online compiler replit
에서 확인해보자.)
(먼저 stack에 저장된 a
가 High Address에 위치하고 있다.
나중에 저장된 ptr_c
는 Low Address에 위치하고 있다.)
1
안녕하세요? 지금 질문하신 내용들은 프로그래밍 언어의 범위를 넘어서 운영체제와 연관이 되는 부분입니다. 저도 운영체제나 컴파일러 전공자가 아니지만 궁금하신 내용과 관련있을 만한 내용들을 알려드리자면,
1. Endianness https://ko.wikipedia.org/wiki/%EC%97%94%EB%94%94%EC%96%B8
메모리에 데이터를 어떤 순서로 기록할지인데 우리의 직관과 다릅니다. 중간의 그림 보시면 쉽습니다. 강의 후반부에서 잠깐 다뤘던 것으로 기억합니다.
2. 스택
윈도우와 리눅스가 메모리 사용법이 다릅니다. 우리가 흔히 알고 있는 상식들은 리눅스 기준입니다. 그래서 강의 후반부에서는 리눅스에서도 주소를 보여드린 것으로 기억합니다.
도움이 되었기를 바랍니다.
답변해주신 내용들 알아보니, 새롭게 만나게 되는 내용들도 많은 것 같습니다.
나중에 C언어 강의 끝나고 복습하면서 다시 돌아봐야겠습니다.
답변 감사드립니다!