메모리
이미테이션 게임이라는 영화를 보니 튜링이라는 사람이 컴퓨터 모델을 처음으로 구현한 사람으로 소개되었다.
영화에는 소개되지 않았지만 따로 위키를 검색해 보니 튜링 기계의 무한히 긴 띠가 컴퓨터 메모리에 비유된다고 설명한다.
긴 띠의 종이 폭 만큼의 데이터 조각 하나 당 크기를 갖을 수 있다.
데이터 조각이 쓰인 위치를 주소라고 부른다.
주소 데이터
0x00 00000000
0x01 00000000
0x02 00000000
0x03 00000000
0x04 00000000
...
주소 데이터
0x00 00000000
0x01 00000000
0x02 00000000
0x03 00000000
0x04 00000000
...
- 데이터 조각 하나를 바이트라고 생각하자.
- 데이터 조각 여러개를 모아 하나의 의미를 이룰 때 short, int, float, double 또는 struct 를 사용한다.
- 여러벌의 데이터 조각은 아래와 같이 데이터가 순차적으로 밀집되어 있다.
int a => 0x7ffc9a38dca4 0x7ffc9a38dca5 0x7ffc9a38dca6 0x7ffc9a38dca7
- int 는 4 바이트 값으로써 시작 주소값은 운영체제가 정하지만 시작 주소값을 기준으로 순차적으로 4 개의 주소 값을 갖는다.
선언된 변수의 주소 값은 영역의 끝 또는 프로그램 종료 시 소유권을 포기한다.
정리
- 어느 위치에 메모리가 선언될지는 운영체제가 정한다.
- 우리는 메모리가 밀집되어 선언된다는 특성을 기억할 필요가 있다.
- 그리고 C 언어로 주소값을 이용해 성능 좋은 프로그램을 만들 수 있다.
포인터
주소값 확인
int value = 10;
printf("%p\n", &value);
실행:
0x7ffc8461ced4
- %p : 포인터 값 출력
- & : 변수 앞에 입력하면 주소값 반환
포인터 변수 선언 및 값 참조
int * ptr_value = NULL;
int value = 10;
ptr_value = &value;
printf("%p\n", ptr_value);
printf("%d\n", *ptr_value);
실행:
0x7fff52d16d94
10
- int * : 변수 타입에 * 를 붙이면 포인터 변수 선언
- NULL : 없음을 의미하며 실제 값은 0
- * : 포인터 변수 앞에 사용하면 값을 참조
포인터 변수는 값을 저장하지 않고 주소 값만 저장한다.
주소값으로 작업하기
함수로 보내기
#include <stdio.h>
static void s_set_value(int value) {
value = 10;
}
static void s_set_value_pointer(int * value) {
*value = 10;
}
int main() {
int val = 0;
s_set_value(val);
printf("s_set_value() : %d\n", val);
s_set_value_pointer(&val);
printf("s_set_value_pointer() : %d\n", val);
return 0;
}
실행:
s_set_value() : 0s_set_value_pointer() : 10
함수 파라메터로 넘어간 값은 메모리 복사된다.
s_set_value():
- s_set_value() 함수로 입력한 val 파라메터는 s_set_value() 함수의 int value 로 복사된다.
- s_set_value() 함수를 빠져나오면서 int value 는 제거된다.
- s_set_value_pointer() 함수로 입력한 val 의 주소값은 s_set_value_pointer() 함수의 int * value 로 복사된다.
- s_set_value_pointer() 함수 안에서 *value = 10 을 통해 해당 주소에 위치한 데이터 공간에 10을 대입 시킨다.
- s_set_value_pointer() 함수를 빠져나오면 int * value 는 제거된다.
- val 값은 10으로 변경되어 있다.
배열을 포인터로 탐색하기
#include <stdio.h>
static void s_traverse_array_with_pointer(char * array) {
char * p = array;
while (*p) {
printf("%c\n", *p);
p++;
}
}
int main() {
s_traverse_array_with_pointer("hello");
return 0;
}
실행:
h
e
l
l
o
- while (*p) ; p 가 가리키는 값이 0 이 아니면 while 문을 수행한다.
- p++ : 주소값에 1 증가 시킨다. (데이터가 순차적으로 밀집된 점을 이용)
- "hello" : 문자열은 char 배열 형태이다.
h e l l o \0
0 1 2 3 4 5
\0 : 문자 표기시 0은 \0 로 표기한다.
오래된 예제 : swap
#include <stdio.h>
static void s_swap(int * a, int * b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int a = 10;
int b = 20;
s_swap(&a, &b);
printf("a: %d, b: %d\n", a, b);
return 0;
}
실행:
a: 20, b: 10
- temp: *a = *b 를 통해 a 값이 변경되기 때문에 기존의 a 값을 저장한 temp 변수가 필요하다.
프로그램 작성 시 임시 변수를 활용해 문제 해결할 수 있는 경우가 많으니 참고하자.
댓글 없음:
댓글 쓰기