2011-07-03 5 views
0

포인터 풀이 죽은포인터 업 캐스팅과 다운 캐스트

int* ptrInt; 
    char * ptrChar; 
    void* ptrVoid; 
    unsigned char indx; 
    int sample = 0x12345678; 

    ptrInt = &sample; 
    ptrVoid = (void *)(ptrInt); 
    ptrChar = (char *)(ptrVoid); 

    /*manipulating ptrChar */ 
    for (indx = 0; indx < 4; indx++) 
    { 
     printf ("\n Value: %x \t Address: %p", *(ptrChar + indx), (ptrChar + indx)); 
    } 

출력 :

Value: 00000078   Address: 0022FF74 
Value: 00000056   Address: 0022FF75 
Value: 00000034   Address: 0022FF76 
Value: 00000012   Address: 0022FF77 

질문 : 왜 샘플 문자 크기의 데이터로 분할되었다? 그리고 포인터 연산이 수행 될 때 어떻게 나머지 값을 얻을 수 있었습니까? 어떻게 가능 했습니까?


포인터 업 캐스팅

unsigned int * ptrUint; 
void * ptrVoid; 
unsigned char sample = 0x08; 

ptrVoid = (void *)&sample; 
ptrUint = (unsigned int *) ptrVoid; 

printf(" \n &sample: %p \t ptrUint: %p ", &sample, ptrUint); 
printf(" \n sample: %p \t *ptrUint: %p ", sample, *ptrUint); 

출력 :

&sample: 0022FF6F  ptrUint: 0022FF6F 
sample: 00000008  *ptrUint: 22FF6F08 <- Problem Point 

질문 : 왜 * ptrUint에 쓰레기 값이 있다는 것입니다? 왜 쓸데없는 값이 비슷합니까? to ptrUint? 이 쓰레기 값을 피하기 위해 malloc() 또는 calloc()을 사용해야합니까? 쓰레기 값을 제거하기 위해 어떤 종류의 해결책을 제안 하시겠습니까?

+0

미안하지만 질문에 너무 집중해야합니다. 올바른 형식을 잊어 버렸습니다. 사과. –

답변

1

첫 번째 예에서는 한 번에 한 바이트 씩 데이터에 액세스 할 수 있도록 char 포인터를 사용하고 있습니다. 메모리는 바이트 주소 지정 가능하므로 포인터에 하나를 추가하면 다음 상위 메모리 주소에 액세스하게됩니다. 이것은 for 루프에서 일어나는 일입니다. 바이트 포인터를 사용하면 컴파일러에서 단일 바이트에만 액세스하도록 지시하고 나머지 비트는 % p로 인쇄 할 때 0으로 표시됩니다.

두 번째 예제에서 나는 어떤 일이 발생하는지 생각해 보면 샘플 바이트에 1 바이트가 할당되고 다음 4 바이트가 ptrUint에 할당되었다고 생각합니다. 따라서 샘플의 메모리 주소에서 시작하여 4 바이트 포인터로 변환하는 값을 얻으면 Sample의 값과 ptrUint의 처음 3 바이트를 더한 값을 볼 수 있습니다. 이것을 char 포인터로 캐스팅하여 출력하면 출력에 8 개만 표시됩니다.

+0

아, 첫 번째 샘플에서 * (ptrChar + indx)가 쓰레기 값을 가질 가능성이 없다고 말하면됩니다. 좋아요, 그 말이 많은 의미가 있습니다. 하지만 * (ptrChar + 0)이 0x78로 시작한 이유는 무엇입니까? 두 번째 샘플에서는 왜 컴파일러가 쓰레기 값을 추가했는지 궁금해했습니다. 왜냐하면'(unsigned int) (charTypeVariable); charTypeVariable은 unsigned int에 맞게 데이터를 0으로 확장하기 때문입니다. 포인터 변수를 다룰 때 다른가? –

+0

리틀 엔디안 (x86) 시스템에서 바이트가 정렬되는 방식입니다. 최하위 바이트는 최하위 메모리 주소에 있습니다. 이 경우 0x78은 샘플로 초기화 된 단어의 최하위 바이트입니다. 반면에 APPLE 컴퓨터는 빅 엔디안이므로 그러한 시스템에서 역순으로 인쇄했을 것입니다. – user623879

+0

또한 가비지 값을 제거 할 방법이없는 경우. '* ptrUint & 0x000000ff; 마스킹이 가능합니까? –

0

이들은 업 캐스팅 및 다운 캐스트가 아니며 이는 일종의 상속 계층을 의미합니다.

첫 번째 예에서는 char (s)에 대한 포인터 인 것처럼 포인터를 정수로 처리합니다. int에 대한 포인터를 증가 시키면 4가 추가되고 char에 대한 포인터를 증가 시키면 1이 추가됩니다 (32 비트 int 및 8 비트 char을 가정). 이들을 역 참조하면 각각 int와 char가됩니다. 따라서 바이트로 단편화됩니다.

두 번째 예제에서는 unsigned char 변수 인 sample을 int에 대한 포인터 인 것처럼 취급하고 역 참조합니다. 본질적으로 0x08 메모리 주소에서 가비지를 읽습니다. &을 잊어 버린 것 같습니다. 또한 1 바이트 char과 4 바이트 int를 4 + 4 바이트가 아닌 두 번째 printf에 전달하여 printf를 망가 뜨리고 스택에서 3 바이트 이상 읽습니다. 우연히 printf의 첫 번째 호출에 주어진 ptrUint 값의 일부입니다. % p 대신 % c를 사용하면 문제가 해결됩니다.

0

기타 답변은 이미 에 대한 설명이 있습니다. 당신은보고있는 것을보고 있습니다.

두 번째 예는 정의되지 않은 동작에 의존한다고 덧붙입니다. 원래 int이 아닌 데이터를 가리키는 int *을 참조 해제하는 것은 유효하지 않습니다. 즉:

char x = 5; 
int *p = (int *)&x; 
printf("%d\n", *p); // undefined behaviour 
관련 문제