C 자료형 형변환 - sonkoni/Koni-Wiki GitHub Wiki

기본 자료형과 포인터 자료형의 형변환

컴파일러에게 자료형을 변환한다는 의도를 명확하게 밝혀주는 것이 명시적 형변환, 즉, 타입 캐스팅이다.

== 명시적 형변환 ==
(자료형)변수
(자료형)값

== 특정 자료형 포인터로 변환 ==
(자료형 *)포인터

== 특정 자료형 포인터로 변환 후 역참조
*(자료형 *)포인터

기본 자료형 변환

int a = 32; int b = 7; float num;
num = a / b;  // 정수 ÷ 정수 = 정수가 된다. 소숫점을 다 짤라먹은 다음 num 에 할당된다.
printf("=> %f\n", num);
// => 4.000000
int a = 32; int b = 7; float num;
num = (float)a / b;     // 타입캐스팅. 실수 ÷ 정수 = 실수가 된다.
printf("=> %f\n", num);
// => 4.571429

포인터 변환

큰 자료형 포인터를 작은 자료형 포인터로 캐스팅했을 때

작은 자료형의 자릿수에 맞는 수만 출력된다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int *numPtr = malloc(sizeof(int));
    char *cPtr;
    *numPtr = 0x12345678;

    cPtr = (char *)numPtr;              // int 포인터롤 char 포인터로 변환하여 저장
    printf("%p: 0x%x\n", cPtr, *cPtr);  // 메모리 주소는 동일하며, 자신의 자료형에 따라 읽어오는 크기만 달라진다.
    printf("%p: 0x%x\n", numPtr, *numPtr);

    free(numPtr);
    return 0;
}
// 0x600001878030: 0x78
// 0x600001878030: 0x12345678

캐스팅이라는 것은, 자료는 동일한데 읽어오는 범위가 다른 것이다. 이 부분 관련해서는 공용체와 엔디언 참고하기.

  int  [12] [34] [56] [78] ─┐─┐    Little Endian  int   |78||56||34||12|
short    x    x  [56] [78]  ▼ │    Little Endian short  |78||56|
 char    x    x    x  [78]    ▼    Little Endian char   |78|

기본 자료형에서는 이렇게 읽어온 데이터 자체가 해당 변수의 스토리지에 직접 저장되기 때문에 본래 자료로 되돌아갈 수 없다. 하지만 포인터의 경우 스토리지의 주소를 동일하게 저장하고 읽어오는 범위를 달리 하겠다는 것이므로, 다시 본래의 자료로 캐스팅했을 경우 손실이 발생하지 않고 되돌릴 수 있다.

int *other = (int *)cPtr;
printf("%p: 0x%x\n", other, *other);
// 0x6000024f8030: 0x12345678

작은 자료형을 큰 자료형으로 캐스팅했을 때

메모리 침범이 일어나기 때문에 이렇게 하지 않는다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    short *numPtr = malloc(sizeof(short));
    *numPtr = 0x5678;
    printf("%p: 0x%x\n", numPtr, *numPtr);
    
    // 쓰레기값 채워보기
    numPtr[1] = 0x1020;
    
    // 캐스팅하면 메모리 침범이 발생
    int *sPtr = (int *)numPtr;
    printf("%p: 0x%x\n", sPtr, *sPtr);
    
    free(numPtr);
    return 0;
}
// 0x10520c4a0: 0x5678
// 0x10520c4a0: 0x10205678
//                ---- 쓰레기값
short            [56] [78] ─┐     Little Endian short  |78||56|
  int  [10] [20] [56] [78]  ▼     Little Endian  int   |78||56||20||10|
       ---------                                               --------
        쓰레기값                                                   쓰레기값

포인터를 다른 자료형으로 변환하면서 역참조할 때

포인터를 자료형 * 로 캐스팅 한 뒤 역참조한다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char * argv[]) {
    
    int *numPtr = malloc(sizeof(int));
    *numPtr = 0x12345678;

    printf("=> 0x%x\n", *(char *)numPtr);
                    //  ===============  numPtr 을 char * 로 캐스팅한 후 역참조했다.
    free(numPtr);
    return 0;
}
// => 0x78
⚠️ **GitHub.com Fallback** ⚠️