내장형 하드웨어/C언어

포인터 변수의 변화, 주소 저장 방식 - Big Endian, little Endian

동화다아아 2011. 4. 15. 13:27

변수는 항상 주소값을 가진다.

- 심벌 테이블

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; 

        printf("%08X\n",iNum); //

x

12

34

BB

AA

        ++cp;

        *cp=0xCC;

        printf("%08X\n",iNum); //

x

12

CC

BB

AA

        ++cp;

        *cp=0xDD;

        printf("%08X\n",iNum); //

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과 같다.