const 변수를 불변하게 만들고 싶을때 사용한다.(immutable)

요즘 js, React쪽에서는 웬만한 변수는 다 const로 바르고 그게 아닌 경우에만 let(mutable)로 선언한다.

 

C에서도 const를 당연히 사용하는데 포인터에 사용할 때 귀여운 상황이 벌어진다.

 

1. 포인터가 담은 값(주소)를 불변하게 할 것인가

2. 포인터가 담은 값(주소)로 간뒤에 그 값을 불변하게 할 것인가(* 로 접근)

 

 

주소냐, 값이냐

C언어 포큐아카데미

왼쪽의 int* const p = &num은 포인터의 값 즉 주소를 변경하는 것을 막는 코드이다.(1번)

오른쪽의 const int* p = &num은 포인터가 가르키는 값을 변경하는 것을 막는 코드이다.(2번)

실제로 2번 값을 막는 것이 훨씬 많이 쓰이며 중요하다고 한다.

 

'C' 카테고리의 다른 글

C언어 구조체  (0) 2019.12.18
C언어 포인터 배열  (0) 2019.12.13
C언어 배열과 포인터 차이점  (0) 2019.12.12
C 스택 메모리 해부(어셈블리어)  (3) 2019.12.09
C언어 Char, int 정리  (0) 2019.12.05

배열은 주소다. 포인터 변수도 주소를 값으로 가진다.

 

배열과 포인터는 맥락상 거의 같다. 하지만 포인터에서는 먹히고 배열에서는 안되는게 몇가지가 있다.

 

이 차이점을 분명히 하면서 포인터에 대한 이해도를 높이자.(포큐아카데미 설명이 정말 자세하다)

 

sizeof

C언어 포큐아카데미

sizeof으로 크기를 알고 싶을때 포인터는 변수 임으로 4바이트(사용하는 bit수에 따라 다름)를 반환값으로 가지지만 배열은 해당 원소의 개수 X 자료형의 크기를 반환한다.

 

 

배열 문자열

C언어 포큐아카데미

배열로 Monday 라는 문자열을 만들게 되면 day1 변수는 스택 메모리에 저장되며 값 또한 실제로 존재한다.

day[0]은 "M" day[1]은 "o" ... 이런식으로 물론 변경도 가능!

 

 

포인터 문자열

C언어 포큐아카데미

포인터로 day2 문자열 변수를 만들게 되면 day2라는 변수는 스택에 저장 되지만 값으로는 "Monday" 문자열의 주소값을 가짐 또한 "Monday" 문자열의 메모리 저장 공간은 데이터 영역임.(값 변경 불가능 ReadOnly)

 

 

포인터, 배열 대입 차이점

배열로 만든 문자열 수정 가능 BUT 포인터로 만든 문자열 수정 불가

 

배열은 상수다! 이말을 기억하면 안되는것들을 판단할때 참 편하다. 위 처럼 포인터변수는 값을 대입할 수 있지만 배열 상수는 불가!

 

 

포인터 변수는 증감을 할 수 있지만 배열 상수는 불가!

 

 

'C' 카테고리의 다른 글

C언어 구조체  (0) 2019.12.18
C언어 포인터 배열  (0) 2019.12.13
C 포인터 const  (0) 2019.12.12
C 스택 메모리 해부(어셈블리어)  (3) 2019.12.09
C언어 Char, int 정리  (0) 2019.12.05
스택메모리

 

각 함수에서 사용하는 지역 변수, 매개 변수 등을 임시적으로 저장하는 공간이다.

스택 메모리의 크기는 프로그램 빌드 시에 결정되며 위치는 실행 시에 결정된다.

 

간단한 예제(포큐 아카데미 C 강좌)

 

위의 간단한 예제로 설명하자면 main 함수의 int a, int b 그리고 add 함수로 넘겨주는 매개변수 a, b 모두 지역, 매개변수 임으로 스택메모리에 값이 저장된다.

 

C언어에서는 New라는 키워드가 없는데 이는 기본적으로 변수를 선언하면 변수가 스택메모리에 할당되기 때문이다.

C언어 기본 자료형 변수(char, int, float)는 스택 메모리에 할당되며 기본 자료형을 함수 매개변수로 전달하면 스택에 복사본을 만든다(값복사, 값형) 

반대로 다른언어에서 처럼 malloc을 쓰면 Heap 영역에 할당된다. Heap 영역에 메모리를 할당하면 운영체제가 프로그래머가 요구한 메모리 사이즈를 검색하고 반환하며 크기가 가변적이라 메모리에 구멍이 숭숭뚫린다.

 

 

스택 메모리 조금 더 자세히

스택 메모리(포큐 아카데미 C 강좌)

 

1. 스택은 큰주소에서 작은 주소로 쌓인다

2. EBP(Extended Base Pointer) : 현재 스택 프레임의 첫 주소(Base 주소)

3. ESP(Extened Stack Pointer) : 현재 스택 포인터

4. 스택 프레임(stack frame) : 각 함수가 사용하는 스택 메모리의 범위

 

스택 메모리 + 어셈블리어

 

어셈블리어 Mov(포큐 아카데미 C 강좌)

왼쪽은 어셈블리어 오른쪽은 그에 대응되는 스택 메모리의 그림이다.

1. esp를 ebp로 Move해라! 그러니깐 같은 것을 가르켜라

 

 

어셈블리어 메모리 영역 확장(포큐 아카데미 C 강좌)

2. esp를 14h(16진수) 즉 십진수 20만큼 sub(빼라) -> ESP 영역을 20만큼 확장해라 한 블럭이 4바이트니 5칸 밑으로 ESP를 내려라

 

어셈블리어 값 할당 (포큐 아카데미 C 강좌)

3. 주소 ebp - 4 즉 0x0073FE68에 0을 넣어라. ebp - 8 주소에 1을 넣어라, ebp -0Ch 주소에 2를 넣어라

 

어셈블리어 매개변수 전달 (포큐 아카데미 C 강좌)

4-1. eax에 ebp-0Ch의 값을 넣고, ecx에 ebp-8의 값을 넣어라(eax, ecx는 CPU 레지스터 영역임) 

4-2. 아까 담은 ecx의 값을 현재 스택 포인터인 esp에 넣어라 그리고 esp+4에는 eax를 넣어라

 

방금 4줄의 어셈블리어가 add 함수에 매개변수를 전달하는 방식이다

 

add 함수 Call 및 돌아갈 주소 push (포큐 아카데미 C 강좌)

5. 00011040이라는 주소를 Call한다(add 함수) 그리고 다시 돌아올 주소 0001102D를 ESP-14h 주소에 add한다.

 

add 함수 시작 전(포큐 아카데미 C 강좌)

6. 호출자 함수의 EBP를 PUSH 한다. 호출된 add 함수가 끝나고 다시 main함수로 돌아가야하니깐

 

add 함수 시작 전(포큐 아카데미 C 강좌)

7. EBP를 ESP로 move한다

 

add 함수 스택 메모리 확보 (포큐 아카데미 C 강좌)

 

8. ESP를 0c(12) 만큼 늘림으로서 add 함수의 스택 메모리 영역 확보

 

add 함수 res 변수 생성(포큐 아카데미 C 강좌)

 

9-1. eax, ecx, edx 에 2,1,1을 담고 dex에 ebp+0Ch 값을 더한다 1+2 = 3 

9-2. edx의 값을 ebp-4에 할당한다 즉(res 변수)

 

 

add 함수 인자 생성 (포큐 아카데미 C 강좌)

 

10-1. edx에 ebp-4를 할당(의미없음)

10-2. eax의 값(2)를 ebp -8에 할당

10-3, edx의 값을 eax에 할당(의미없음)

10-4, ecx의 값(1)을 ebp-0c에 할당 

 

add 함수 스택 영역 해제(포큐 아카데미 C 강좌)

11. esp에 0c를 add 함으로서 add 함수의 스택 영역을 해제한다. 여기서 중요한점은 3,2,1과 같은 값을 지우지 않는다는 점이다. 나중에 다른 함수가 해당 주소를 다시  읽었을때 3,2,1 같은 쓰레기 데이터가 남아있는 이유가 이때문이다.

 

add 함수 스택 영역 해제(포큐 아카데미 C 강좌)

12. 0x0073FE6C의 주소로 ebp를 이동하면서 pop

 

add 함수 종료 return (포큐 아카데미 C 강좌)

13. return 명령어 실행 : 0x0001102D 의 주소로 return (add 함수 종료)

 

14-1. esp, 14h 만큼 add : esp가 ebp를 가르키게함 (메모리 축소)

14-2. ebp를 pop

14-3. return 후 종료

'C' 카테고리의 다른 글

C언어 구조체  (0) 2019.12.18
C언어 포인터 배열  (0) 2019.12.13
C 포인터 const  (0) 2019.12.12
C언어 배열과 포인터 차이점  (0) 2019.12.12
C언어 Char, int 정리  (0) 2019.12.05

+ Recent posts