포인터 변수의 변화, 주소 저장 방식 - Big Endian, little Endian
변수는 항상 주소값을 가진다.
- 심벌 테이블
type |
name |
address |
int
|
x
|
0012FF7C
|
- 디버그시 메모리 창에 보이는 내용(visual studio 6.0)
주소 |
Hexa |
Ascii |
|
|
|
⇒ 주소가 없으면 우리는 값을 찾을 수가 없다.
⇒ 변수의 type은 심볼 테이블에 있어야만 cpu가 알 수 있다.
⇒ 컴파일이 완료되는 시점에는 주소 값만 남아있다.
→ mov dptr [0012FF7C],3; (→어셈블리 예)
[참고]
→ 어셈블리어가 속도, 최적화가 가장 높다.
→ 하지만 작성과 해석이 불편하므로, 어셈블리의 최적화에 가장 근접한 C를 사용한다.
→ C의 최적화가 높아지는 것은 컴파일러가 발전하고 있기 때문이다.
→ 하지만 어셈블리만이 접근할 수 있는 구역이 있다.
※ 타입에 관계없이 포인터는 모두 4byte 이다.
⇒ 주소 값을 손실하지 않으려면 4byte가 필요하다.
이는, 우리가 쓰는 컴퓨터가 현재 대부분 32bit 이고 따라서 BUS의 크기가 4byte이기 때문이다. 하지만 현재는 4byte라도, 컴퓨터가 64bit로 바뀐다면 포인터는 8byte가 될 것이다. BUS 크기가 8byte가 되기 때문이다.
→ ‘*’ 문자는 포인터변수가 가리키는 메모리에 들어있는 값.
// short 형의 포인터 변수가 int 형의 데이터를 접근하는 프로그램
#include<stdio.h>
int main()
{
int iNum;
int *ip; // ip는 int 형을 가리키는 포인터 변수
short *sp; // sp 는 short 형을 가리키는 포인터 변수
iNum=0x0F5A0B43; // iNum의 초기화
ip=&iNum; // ip의 초기화(iNum의 주소값을 대입)
printf("iNum: %x ip : %p\n", iNum, ip);
sp = (short *)ip; // sp는 iNum을 가리킨다.
printf("sp: %p, *sp: %x\n",sp,*sp);
sp++; // sp가 iNum의 세 번째 바이트를 가리킨다.
printf("sp: %p, *sp: %x\n", sp, *sp);
return 0;
}
⇒ 실행결과
⇒ 변수 ip와 sp는 각각 int 형과 short 형을 가리키는 포인터로 선언되었다.
// 포인터를 사용하여 주소의 값 변화 확인
x |
12 |
34 |
56 |
78 |
라고 선언하고 1byte 씩 주소값을 바꾸어 본다.
#include<stdio.h>
int main()
{
int iNum=0x12345678; // iNum의 주소값 선언
unsigned char *cp;
cp=(unsigned char*)&iNum; // 4byte iNum을 cp에 넣기 위해서는 형을 맞추어주어야 한다. 그래서 (unsigned char*) 라는 캐스팅을 사용하여 형을 맞춰 주었다.
printf("%08X\n",iNum);
*cp=0xAA;
printf("%08X\n",iNum); // iNum의 처음 주소에 AA를 집어 넣는다.
x |
12 |
34 |
56 |
AA |
++cp; // 주소에서 1을 더한다. cp=cp+1→ 1byte씩 더한 것
*cp=0xBB;
x |
12 |
34 |
BB |
AA |
++cp;
*cp=0xCC;
x |
12 |
CC |
BB |
AA |
++cp;
*cp=0xDD;
x |
DD |
CC |
BB |
AA |
return 0;
}
⇒ 실행결과
⇒ 사람은 비교계산은 앞에서 덧셈 계산은 뒤에서부터 하는 성향이 있으며 이것은 컴퓨터에도 해당한다.
⇒
화면표시 |
실제 저장 |
1 2 3 4 +5 6 7 8 6 9 1 2 |
4 3 2 1 +8 7 6 5 2 1 6 9 |
→ 즉, 우리가 주로 쓰는 pc에서는 1 2 3 4 라는 수를 입력하면 메모리에 4 3 2 1로 저장한다. 왜냐하면 이것이 연산이 더 빠르기 때문이다.
⇒ 주로 pc의 경우가 이렇게 저장을 하는데 우리가 사용하는 일반 pc는 계산이 더 중요하기 때문이다. 반대로 기상청 등에서 쓰는 슈퍼 컴퓨터는 대체로 논리 연산이 중요하므로 화면표시의 순서대로 저장한다.
⇒ 좀더 자세히 살펴보면
|
Start |
|
|
End |
원본 |
12 |
34 |
56 |
78 |
→ 메모리에는
|
Start 1001 |
1002 |
1003 |
End 1004 |
|
논리 |
12 |
34 |
56 |
78 |
→ Big Endian |
계산 |
78 |
56 |
34 |
12 |
→ Little Endian |
|
1001 End |
1002
|
1003
|
1004 Start |
|
라고 저장된다.
⇒ 당연히 char형은 1byte이므로 뒤집어 지지 않는다.
⇒ 실수도 역시, little Endian 으로 저장된다.
→ float 5.765 는 0100 0000 1011 1000 0111 1010 1110 0001 로 저장되고 이것은 40B87AE1과 같다.
'내장형 하드웨어 > C언어' 카테고리의 다른 글
포인터 - CPU와 BUS MEMORY간 전송과정, void, return, 함수 (0) | 2011.04.19 |
---|---|
포인터 - 포인터 변수가 가리키는 자료형의 의미, 세그먼테이션(segmentation) (0) | 2011.04.18 |
무한반복문, break, 포인터 (0) | 2011.04.14 |
for문 (초기식과 증감식의 변형, 무한반복문) (0) | 2011.04.13 |
VMware player 설치, 리눅스 명령어 (0) | 2011.04.11 |