본문 바로가기

고급C,C++

[고급C언어] *((int*)voidp)++


int imsi[]={7, 4, 9};

void *voidp;

 

voidp=imsi;

 

for(i=0;i<sizeof(INT) / sizeof(int); i++)

(1) printf("%d\n", *((int *)voidp)++);       // * ( ( int *) voidp ) ++

(2) printf("%d\n", *(int *)voidp++);         // * ( int * ) voidp ++

 

[출력결과]

(1) 7 4 9

(2) 7 (Segmentation Fault) memory dumped

두번째 수행문은 문제를 발생시킨다.

 

위의 (1)번은 ((int *)voidp)가 하나의 덩어리가 되었으므로 *imsi++와 같은 의미로 사용될 수 있다는 것을 알 수 있다.

*((int *)voidp)++ 수식을 하나씩 정리해보자.

 

- voidp

void형 포인터 변수이다. 어떠한 주소 값도  들어갈 수 있으며 단지 가리키는 곳에서 몇 바이트 읽어올지 알 수 없으므로 캐스트 연산자를 이용하는 것이다.

 

- (int *)voidp

voidp에 있는 값을 int형 주소값으로 변환한다. 이 말은 voidp에서 나중에 값을 꺼내올때 voidp가 가리키는 곳에서부터 4바이트를 읽어 온다는 말과 같다.

 

- (int *)voidp)++

void에 있는 값을 int형 주소 값으로 변환하고 ++를 이용하여 int형만큼 분기한다. 그런데 ++는 후치 연산이기 때문에 다음에 이를 적용받게 된다.

 

- *(int *)voidp)++

++에 걸리는 대상체가 괄호 전체가 되므로 위의 수식에서 ++의 대상체는 (int *)voidp가 된다. voidp에 들어있는 값을 int형을 가리키는 주소 값으로 변환했기 때문에 ++ 수식을 사용할 수 있는 것이다. ++에 걸리는 대상체가 "int *"라는 것을 다음 프로그램으로 확인할 수 있다.

 

main()

{

    int imsi[3] = {6, 3, 7};

    int *imsip;

    void *voidp;

 

    imsip = imsi;

    voidp = imsip;

 

    printf("1. %d\n", * ( ( double * ) voidp) ++);

    printf("2. %d\n", * (int *)voidp);

}

 

[출력결과]

1. 6

2. 7

*((double *)voidp)++에 의해서 증가되는 주소 값은 8바이트가 된다. ++의 대상체는 (double *)voidp이기 때문이다. 8바이트가 움직인 상태에서 *(int *)voidp를 출력해보면 무엇이 나오겠는가? 당연히 7이라는 값이 나올 것이다.

 

 

 

 

출처: 다시 체계적으로 배우는 C언어 포인터(정보문화사:정재은 저)