포인터로 바이트 단위 조작을 하여 실질적으로 메모리를 들여다볼 수 있다.
포인터의 자료형을 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++;
}
}
포인터를 바이트 단위로 이동시키며 연산하였다! 현대의 프로그래밍 언어에서 할 수 없는 일이라 그런지 희열이 느껴진다.
보이드 포인터는 상급 주제이다. 여기서는 간단히 선언만 보고 가겠다.
#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언어 튜토리얼의 포인터 실습은 이정도로 마무리하고 다음에 관련 주제가 나오면 다루도록 하겠다. 어차피 배열이나 구조체나 힙이나 다들 포인터를 조작해야 한다. 한번에 이해하기 보다 관련 주제에서 한층 더 깊은 이해도를 목표로 하는것이 바람직하다.