본문 바로가기

Software

sizeof()와 포인터

개발 도중 sizeof()를 통해 *포인터 변수로 참조된 Array list의 크기를 구하고자 하였다.

너무나도 기초적인 부분이라 안 되는 것을 알고 있었지만, 구하고 싶었다.

 

결론부터 언급하자면 sizeof()는 컴파일 타임에 결정지어지는 연산자이다.

 

다음의 코드를 보자

 

data type이 char인 Array list를 각각 크기가 10과 40으로 선언하였고,

포인터 변수에 런타임(runtime)에 크기가 40인 arr_two의 주소를 지정하였다.

 

결과는 10, 40, 1 이 나오는 것을 확인할 수 있다.

각 두 개의 array list의 sizeof() 연산에 대해선 명확하게 10과 40을 출력하였다.

그러나 포인터가 가리키는 array list의 size를 구하고자 하였는데, 왜 sizeof()는 1이라는 값을 출력하였을까?

 

상단에서 언급하였지만, sizeof()는 컴파일 타임에 결정지어지는 연산자 이기 때문이다.

local 변수로 할당된 list에 대해선 memory의 stack에 할당되어 사전에 컴파일 타임에 계산된다.

하지만 runtime에 지정된 array list의 참조 변수일뿐 이는 heap에서 관리가 되며,

실질적으로 컴파일 타임에서는 해당 포인터 변수가 가리키는 변수 즉 arr_two의 첫 번째 요소의 size인 1을 표기하게 되는 것이다.

 

이를 확인하기 위해 해당 코드의 asm 코드를 확인해 보았다.

 

 

gcc의 -S 옵션을 통해 명령을 수행하면 "Compile only, do not assemble or link" 설명과 같이 .S 어셈블리 파일 생성한다.

생성된 .s 파일을 vi를 통해 읽어보면 다음의 결과를 확인할 수 있다.

 

23번, 31번, 40번 라인 확인 시 movl 명령을 통해 10, 40, 1 각각 이미 sizeof() 연산에 의한 값이 이미 계산되어, 각 레지스터에 할당되어진다. sizeof() 연산자는 컴파일 타임에 수행되는 연산자 이므로, 런타임에 stack 영역에 존재하지 않는 reference data의 size는 알 수 없다.

 

그렇다면 나는 왜 이것을 혼돈하였을까? 에 대하여 고민해 보았다.

그 원인은 sizeof()를 함수의 형태로 보고 있었다.

sizeof()는 함수가 아닌 연산자이다. 컴파일러는 sizeof를 일련의 명령어로 컴파일하기 때문이다.

 

함수와 연산자의 차이점

함수 호출 코드는 함수 코드가 있는 주소로 이동하게 만들고, 연산자는 컴파일러가 정해놓은 명령으로 컴파일을 수행한다.
sizeof가 괄호로 둘러쌓여 함수처럼 보이지만 실제로는 컴파일시에 일련의 명령으로 바뀌어지는 것이다.
그러므로 연산자이다.

 

나는 sizeof()를 연산자로 보지 않고, 함수로 인지하고 있었다.

그렇기 때문에 runtime에 argument의 형태로 해당 포인터가 가리키는 data를 전달하였다고 생각하였으며,

그 data type에 맞는 size를 return 받기를 원했다.

 

아주 기초적인 개념의 인지부조화로  인해 발생된 이슈라고 생각하며, 반성문을 마친다... OTL....

반응형

'Software' 카테고리의 다른 글

Yocto Project 소개  (0) 2021.08.18
Error message 모음  (0) 2019.02.08
Secure Cordng C - Expression  (0) 2018.08.30
Secure Cordng C - Declaration  (0) 2018.07.24
Secure Cordng C - Preprocessor  (0) 2018.07.23