일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 깃
- Data Structure
- Houdini
- 포인터
- 유니티
- dart 언어
- 다트 언어
- C++
- Python
- 도커
- git
- HTML
- c# 추상 클래스
- c언어
- github
- jupyter lab
- Unity
- C# delegate
- 플러터
- vim
- c# 윈폼
- 구조체
- jupyter
- c# winform
- gitlab
- c#
- docker
- C언어 포인터
- Flutter
- Algorithm
Archives
- Today
- Total
nomad-programmer
[Programming/C] 주소와 메모리 본문
#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)는 쓰레기 값이 된다.
'Programming > C' 카테고리의 다른 글
[Programming/C] 다차원 배열 주소의 의미 (0) | 2020.06.22 |
---|---|
[Programming/C] 상수 주소를 사용한 배열 요소 접근 (0) | 2020.06.21 |
[Programming/C] 주소의 형 변환 (0) | 2020.06.21 |
[Programming/C] 개발 도구들 (0) | 2020.06.21 |
[Programming/C] 자동화된 테스트 (0) | 2020.06.21 |
Comments