2013-04-07 5 views
2

나는 반 친구가 게시 된 일부 코드를 찾고 있어요 그리고이 예제를 위해 단순화되었습니다C 코드 포인터 퍼즐

int main() 
{ 
    int n = 0x4142; 
    char * a = (char *) &n; 

    char * b1 = (((char *) &n) + 1); 
    char * b2 = (((int) &n) + 1); 

    printf("B1 Points to 0x%x - B2 Points to 0x%x\n", b1, b2); 

    printf("A Info - 0x%x - %c\n", a, *a); 
    printf("B1 Info - 0x%x - %c\n", b1, *b1); 
    printf("B2 Info - 0x%x - %c\n", b2, *b2); 

    return 0; 
} 

출력은 : 그것은 오류를 세그멘테이션

B1 Points to 0xcfefb03d - B2 Points to 0xcfefb03d 
A Info - 0xcfefb03c - B 
B1 Info - 0xcfefb03d - A 
Segmentation fault (core dumped) 

b2를 인쇄하려고 할 때. 반면 출력에는 오류가 발생하는 대신 다음 줄이 포함되어야한다고 생각하는 반면 :

B2 Info - 0xcfefb03d - A 

왜 이런 경우입니까? b1과 b2는 모두 char *이고, 둘 다 동일한 주소를 가리 킵니다. 이것은 64 비트 머신에서 sizeof (char *) == 8이고 sizeof (int) == 4 인 경우에 해당합니다.

+0

내가 프로그램에 오류가 표시 해달라고 : http://codepad.org/VU8upOdl – karthikr

+0

그래, 그게 내 급우가 지적한 문제 야. 코드 패드에는 문제가 없지만 64 비트 컴퓨터에서는 문제가 발생합니다. 모두 OS X 10.7 64 비트 및 우분투 리눅스 64 비트. –

+1

'% x'은 인수를'unsigned int'로 해석합니다 (C11 §7.21.6.1.8). 포인터를 인쇄하려면'% p'를 사용해야합니다. – DCoder

답변

3

있지만 64 비트 컴퓨터

가능성이 이유에 세그먼테이션 폴트 (segfault)는 플랫폼에, 포인터가 64 비트이고의 int는 32 비트, 즉이다. 따라서 포인터를 int으로 캐스팅하면 정보가 손실됩니다.

test.c:7:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 

이 다음과 같은 프로그램을 사용하여 쉽게 알 수있다 : 내 컴퓨터에서

#include <stdio.h> 

int main() 
{ 
    char *s = ""; 
    printf("%p %p\n", s, (char*)(int)s); 
    return 0; 
} 

, 이것은 두 개의 서로 다른 주소를 인쇄를 (두 번째의 상단을 가지고

내 컴파일러는 특별히 이것에 대해 경고 비트 잘게). 내가 확실히 이해하지 못하는 것을

는 B1 및 B2 모두 * 문자이며, 그들은이 같은 주소

에 둘 점은 사실, 그들은 같은 주소를 가리 없다는 것입니다. printf() 형식 지정자가 모두 잘못되었습니다. 첫 번째 printf()은 다음과 같아야합니다

printf("B1 Points to %p - B2 Points to %p\n", b1, b2); 

이를 실행할 때 주소가 다른 것을 볼 수 있습니다. 포인터의 크기가 이상 (보통 64 비트 CPU에서의 경우) INT의 크기보다 경우

+0

정보의 손실은 당연한 일이지만 이해할 수없는 것은 b1과 b2가 모두 char *이고 둘 다 같은 주소를 가리킨다는 것입니다. 나는 아직도 뭔가를 놓치고 있어야합니다. –

+1

@tigger : 답변에 대한 설명을 추가했습니다. 간단히 말해서,'printf()'형식 지정자가 잘못 되었기 때문에 같은 * 것처럼 보입니다. 사실 주소가 다릅니다. – NPE

+0

그래, 나는 그것을 깨닫지 못해서 차기하고있다. 감사합니다 –

1

(int)&n이 거기에 얼마나 많은 비트 n의 주소를자를 수 있습니다 int, IOW는, 당신은 가짜 얻을 , 당신이 안전하게 참조 할 수없는 잘린 주소/포인터.

+0

잘림은 의미가 있지만, 이해가 안되는 것은 b1과 b2가 모두 char *이고 두 주소가 같은 주소를 가리킨다는 것입니다. –

+2

잘림이란 동일한 주소를 가리 키지 않음을 의미합니다. 하나의 주소는 맨 위에 0의 무리가 있습니다. –

+0

예. 감사합니다. 저를 혼란스럽게 한 것은 제 인쇄물이었습니다 ... –

1

예에서 int은 4 바이트이므로 캐스팅하고 b2에 할당하려고하면 &n의 값이 잘립니다. uintptr_t, 안전하게 플랫폼 용량에 관계없이 포인터를 저장할 수있는 부호없는 정수 형식을 사용, 정수로 포인터 값을 치료하려면

char * b2 = (((int) &n) + 1); 

은 다음과 같아야합니다

char * b2 = ((uintptr_t) &n) + 1;