포인터로 바이트 단위 조작을 하여 실질적으로 메모리를 들여다볼 수 있다.

 

포인터의 자료형을 1바이트인 char형으로 지정한다. 변수에 대해서 형변환이 필요하다.

 

아래 예제와 같다.

#include <stdio.h>

void main(){
    int num1 = 0x11223344;
    char *ptr = (char *)&num1;

    printf("Dec: %d Hex: %X\n",num1,num1);
    for(int i=0; i<sizeof(int); i++){
        printf("address : %p,  value(hex) : %X \n",ptr,*ptr);
        ptr++;
    }
}

실행결과

 

16진수로 num1을 초기화한 것은 8비트 단위의 메모리를 보기 위해서이다.

 

int형으로 저장하면 1바이트에 11 22 33 44 라고 잘라서 저장이 된다.

 

메모리의 처음 주소가 0x0000 이면

0x0000 : 11

0x0001 : 22

0x0002 : 33

0x0003 : 44

이 되야할 것 같은데 실행결과는 그렇지 않다. 왜냐하면 메모리에 접근하는 방식의 차이 때문이다.

 

0x0000 : 44

0x0001 : 33

0x0002 : 22

0x0003 : 11

실제로는 이렇게 배치되어 있다. x86 계열 프로세서를 사용하고 윈도우 운영체제를 사용한다면 리틀엔디안 방식이다. 이 프로그램을 돌려보면 알 수 있다.

 

32비트라면 8비트씩 분리되어 제일 낮은 자리수 0~255까지 첫번째로 온다.

 

16진수를 사용하면 바이트 단위의 조작도 가능하다.

#include <stdio.h>

void main(){
    int num1 = 0x11223344;
    char *ptr = (char *)&num1;
    char *ptr2 = (char *)&num1;

    printf("Dec: %d Hex: %X\n",num1,num1);

    for(int i=0; i<sizeof(int); i++){       
        printf("address : %p,  value(hex) : %X \n",ptr,*ptr);
        *ptr += 0x11;
        ptr++;
    }
    printf("\n============== after ==============\n\n");
    for(int i=0; i<sizeof(int); i++){
        printf("address : %p,  value(hex) : %X \n",ptr2,*ptr2);
        ptr2++;
    }
}

 

포인터를 바이트 단위로 이동시키며 연산하였다! 현대의 프로그래밍 언어에서 할 수 없는 일이라 그런지 희열이 느껴진다.

 

void 포인터

보이드 포인터는 상급 주제이다. 여기서는 간단히 선언만 보고 가겠다.

 

#include <stdio.h>

void main(){

    int num1 = 10;
    char ch1 = 'A';
    float fl1 = 10.1f;
    void *vp;

    int *ptr1 = &num1;
    char *ptr2 = &ch1;
    float *ptr3 = &fl1;
 
    vp = &fl1;
    float *ptr4 = (float *)vp;

    printf("VAL : %d    ADRS : %p\n",*ptr1, ptr1);
    printf("VAL : %d    ADRS : %p\n",*ptr2, ptr2);
    printf("VAL : %0.3f    ADRS : %p\n",*ptr3, ptr3);

    printf("VAL : %0.3f  ADRS : %p\n",*ptr4, ptr4);
    printf("ADRS : %p\n", vp);
}

보이드 포인터는 포인터의 정확한 형태를 알 수 없을 때 사용한다.

 

모든 자료형의 포인터를 할당가능하지만 자신은 사용할 수가 없다. 주소값은 볼 수 있으나 사용은 안된다.

 

사용하기 위해서는 다시 형변환을 해야 한다.

 

#include <stdio.h>

int DataProcess(void *ptr, char mode)
{
    int result;
    if(mode == 1) result = *(char *)ptr;
    else if(mode ==2) result = *(short *)ptr;
    else if(mode ==3) result = *(int *)ptr;
    return result;
}

void main(){
    int hexnum = 0x11223344;
    printf("data : %X\n " ,DataProcess(&hexnum,1));
    printf("data : %X\n " ,DataProcess(&hexnum,2));
    printf("data : %X\n " ,DataProcess(&hexnum,3));
}

데이터를 넘겨주고 출력을 지정하는 함수를 만들었다. int형 변수가 void 포인터에 할당되고 출력시에는 int short char 중에 선택할 수 있다. 이로써 좀 더 유연한 프로그램이 되었다. 

 

이번 C언어 튜토리얼의 포인터 실습은 이정도로 마무리하고 다음에 관련 주제가 나오면 다루도록 하겠다. 어차피 배열이나 구조체나 힙이나 다들 포인터를 조작해야 한다. 한번에 이해하기 보다 관련 주제에서 한층 더 깊은 이해도를 목표로 하는것이 바람직하다.

공유하기

facebook twitter kakaoTalk kakaostory naver band