Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
05-17 00:00
관리 메뉴

nomad-programmer

[Programming/C] 주소와 메모리 본문

Programming/C

[Programming/C] 주소와 메모리

scii 2020. 6. 21. 17:20
#include <stdio.h>

void main() }
    int n = 100;
    
    // 12ff7c
    printf("%x\n", &n);
    printf("%d %d\n", n, *&n);
}

// 결과
/*

12ff7c
100 100

*/

int형 변수 n의 주소가 12ff7c라면 시작 주소는 &n이고, 이 주소에 *를 붙여 *&n 은 변수 n의 4바이트 크기의 메모리를 의미하게 된다. 값은 100이다.
*&n 은 n과 같은 메모리의 이름이라고 해도 무방하다. 주소 12ff7c ~ 12ff7f의 4바이트 메모리 이름은 n과 *&n 이다.

& 연산자와 * 연산자는 상반된 개념을 가지고 있다. & 연산자는 변수(메모리 이름) 앞에서만 사용하고 * 연산자는 주소 앞에서만 사용한다. 예를 들어 *N과 가이 사용하면 N은 주소이고 &N과 같이 사용하면 N은 변수(메모리 이름)여야만 한다.
만약 N이 주소라면 *N과 같이 하면 메모리 이름이 되고 &*N과 같이 하면 주소가 되고 *&*N과 같이 하면 메모리가 된다.

 

int형 주소를 char형 주소로 변환하여 각각의 메모리를 1바이트씩 접근하는 예제

#include <stdio.h>

int main() {
    int n = 0x44434241;

    printf("%d %c\n", *(char*)&n, *(char*)&n);
    printf("%d %c\n", *((char*)&n+1), *((char*)&n+1));
    printf("%d %c\n", *((char*)&n+2), *((char*)&n+2));
    printf("%d %c\n", *((char*)&n+3), *((char*)&n+3));

    return 0;
}

// 결과
/*

65 A
66 B
67 C
68 D

*/

&n은 int형 주소이지만 형 변환 연산자를 사용하여 char형 주소로 강제로 형 변환 하는 것을 볼 수 있다. 또 char형 주소로 변환된 주소들은 덧셈할 때 1바이트씩 증가하므로 int형 변수 n이 12ff7c ~ 12ff7f 주소를 사용한다면 각각 12ff7c, 12ff7d, 12ff7e, 12ff7f가 된다.
이 주소들은 char형 주소이므로 * 연산자를 사용하면 1바이트 크기의 정수에 접근할 수 있다. 12ff7c 주소에 0x41이 저장되는 이유는 메모리 저장 방식에 리틀 엔디안을 사용하기 때문이다.

프로세서는 메모리에 데이터를 저장하기 위해 몇 가지 방법을 사용한다. 프로세서의 데이터 저장 방식 중 가장 많이 사용하는 리틀 엔디안(little-endian)과 빅 엔디안(big-endian) 이 있다.
리틀 엔디안은 메모리에 데이터를 저장할 때 낮은 주소에서 높은 주소로 하위 바이트부터 상위 바이트까지 저장하는 방식이고
빅 엔디안은 낮은 주소에서 높은 주소로 상위 바이트부터 하위 바이트까지 저장하는 방식이다.

다음은 주소 1000번지부터 주소 1003번지까지 정수 0x12345678을 저장하는 예이다.

리틀 엔디안: 1000번지에 0x78, 1001번지에 0x56, ... 각각 저장
빅 엔디안: 1000번지에 0x12, 1001번지에 0x34, ... 각각 저장

 

[ ] 연산자를 사용하여 int형 메모리를 1바이트씩 접근하여 정수 대입하는 예제

#include <stdio.h>

int main() {
    int n = 0x44434241;

    printf("%d %c\n", ((char*)&n)[0], ((char*)&n)[0]);
    printf("%d %c\n", ((char*)&n)[1], ((char*)&n)[1]);
    printf("%d %c\n", ((char*)&n)[2], ((char*)&n)[2]);
    printf("%d %c\n", ((char*)&n)[3], ((char*)&n)[3]);

    return 0;
}

// 결과
/*

65 A
66 B
67 C
68 D

*/

 

char형 주소를 int형 주소로 변환하여 값에 접근하는 예제

#include <stdio.h>

int main() {
    char c = 10;

    printf("%d\n", c);
    printf("%d\n", *&c);
    printf("%d\n", *(int*)&c);

    return 0;
}

// 결과
/*

10
10
-858993654

*/

메모리 표현

char형 주소를 int형 주소로 강제 변환한 후 값에 접근한다. 첫 번째 문장과 두 번째 문장은 10이지만 세 번째 문장은 쓰레기 값이 들어갔다.
12ff7c 주소에 10이 저장되고 나머지 12ff7d, 12ff7e, 12ff7f 주소는 데이터를 저장한 것이 아니기 때문에 값을 알 수 없고 12ff7c부터 12ff7f까지의 내용에 접근하는 (*(int*)&c)는 쓰레기 값이 된다.

Comments