프로그래밍 언어/[ C ]

[ C ] 04. 포인터의 형변환

kim.svadoz 2020. 8. 13. 10:04
반응형

[ 포인터의 형변환 ]


#include <stdio.h>
#incldue <stdlib.h>     // malloc, free 함수가 선언된 헤더파일

int main(){
    int *numPtr = malloc(sizeof(int));     // 4바이트만큼 메모리 할당
    char *cPtr;

    *numPtr = 0x12345678;

    cPtr = (char *)numPtr;        // int 포인터 numPtr을 char 포인터로 변환. 메모리 주소만 저장됨

    printf("0x%x\n", *cPtr);    // 0x78 : 낮은 자릿수 1바이트를 가져오므로 0x78

    free(numPtr);        // 동적메모리 해제
    return 0;
}
# 실행 결과
0x78

numPtr에 메모리를 할당하고 역참조하여 0x12345678을 저장했다. 그리고 cPtr = (char *)numPtr;과 같이 int 포인터를 char포인터로 변환하여 메모리 주소을 저장하였다.

이 상태에서 printf로 *cPtr을 출력해보면 어떻게 될까? *cPtr과 같이 역참조하면 numPtr의 메모리 주소에 접근하지만 cPtr은 char포인터이므로 1바이트만큼만 값을 가져온다. 즉, numPtr이나 cPtr이나 안에 저장된 메모리 주소는 같지만 자료형에 따라 역참조했을 때 갑을 가져오는 크기가 결정되기 때문이다.

image-20200731172136528

여기서는 메모리 공간에 0x12345678(리틀 엔디언: 78 56 34 12)이 저장된 상태에서 1바이트 char 크기만큼 낮은 자릿수 값을 가져오므로 0x78이 된다. 자료형이 다른 포인터에 메모리 주소가 이리저리 옮겨 다닌다고 해도 메모리 공간은 그대로이고, 값을 가져오는 크기만 달라진다.

  • 앞의 예제와는 반대로 크기가 작은 메모리 공간을 할당한 뒤큰 자료형의 포인터로 역참조하면 의도치 않은 값을 가져오게 된다.
#include <stdio.h>
#include <stdlib.h>

int main(){
    short *numPtr1 = malloc(sizeof(short));        // 2바이트만큼 메모리 할당
    int *numPtr2;

    *numPtr1 = 0x1234;

    numPtr2 = (int *)numPtr1;        // short 포인터 numPtr1을 int 포인터로 변환. 메모리 주소만 저장됨

    printf("0x%x\n", *numPtr2);        // 0xfdfd1234 : 옆의 메모리를 침범하여 값을 가져옴
                                // 0xfdfd는 상황에 따라서 값이 달라질 수 있음
    free(numPtr1);
    return 0;
}
# 실행결과
0xfdfd1234

이번에는 numPtr1에 2바이트 크기로 메모리를 할당하고 역참조하여 0x1234를 저장했다. 그리고 numPtr2= (int *)numPtr1;과 같이 short 포인터를 int 포인터로 변환하여 메모리 주소를 저장했다.

printf로 *numPtr2를 출력해보면 1234앞에 엉뚱한 값이 붙어서 나온다. 크기가 작은 메모리를 할당한 뒤 큰 자료형의 포인터로 역참조하면 옆의 메모리 공간을 침범하여 값을 가져오게 된다.

image-20200731173004546

malloc 함수로 2바이트만큼 메모리를 할당했으므로 0x1234(리틀 엔디언 : 34 12)만 저장되어 있다. 하지만 이 상태에서 4바이트 int 크기만큼 값을 가져오면 2바이트 크기를 벗어나서 malloc 함수로 할당하지 않은 공간까지 함께 가져오게 된다. 따라서 의도치 않은 값을 가져오게 되므로 주의하자. 참고로 할당되지 않은 공간에는 쓰레기 값이 들어있다.

- 참고

// 참고 // ******************** 포인터 변환과 컴파일경고 *************************
// 일반변수와 마찬가지로 포인터도 변환할 때 자료형이 다르면 컴파일 경고가 발생한다.

int *numPtr = malloc(sizeof(int));        // int 포인터
char *cPtr;            // char 포인터

cptr = numPtr;        // 컴파일 경고 발생
free(numPtr);
# 컴파일 결과
warning C4133: '=': 'int *'과(와) 'char *' 사이의 형식이 호환되지 않습니다.

포인터를 다른 자료형으로 변환하면서 역참조하려면 다음과 같이 ( )(괄호) 앞에 역참조 연산자 *를 붙여주면 된다.

  • *(자료형 *)포인터
#include <stdio.h>
#include <stdlib.h>        // malloc, free 함수가 선언된 헤더 파일

int main(){
    int *numPtr = malloc(sizeof(int));        // 4바이트 만큼 메모리 할당
    char *cPtr;

    *numPtr = 0x12345678;
    printf("0x%x\n", *(char *)numPtr);        // 0x78 : numPtr을 char 포인터로 변환한 뒤 역참조
    free(numPtr);        // 동적 메모리 해제
    return 0;
}
# 실행 결과
0x78

*(char *)numPtr과 같이 char 포인터로 변환한 뒤 역참조 했다. 따라서 0x12345678에서 1바이트 char 크기만큼 낮은 자릿수 값 0x78을 가져온다.

반응형