指针上传和下行

时间:2011-07-03 07:20:35

标签: c pointers type-conversion downcast

指针向下倾斜

    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

问题: 为什么样本被分成char大小的数据?当执行指针运算时,它是如何获得其剩余值的? 这怎么可能?


指针上传

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中存在垃圾值?为什么垃圾值相似 ptrUint?应该使用malloc()还是calloc()来避免这种垃圾值?你建议什么样的补救方法来消除垃圾价值?

3 个答案:

答案 0 :(得分:1)

在第一个示例中,您使用的是char指针,因此一次只能访问一个字节的数据。内存是字节可寻址的,因此当您向指针添加一个时,您将访问下一个更高的内存地址。这就是for循环所发生的事情。使用字节指针告诉编译器只访问单个字节,当使用%p打印时,其余位将显示为0.

在第二个例子中,我认为发生的事情是为样本字节分配了一个字节,然后将下面的4个字节分配给ptrUint。因此,当您从sample的内存地址开始获取值并将其转换为4字节指针时,您只需看到Sample中的值加上ptrUint的前3个字节。如果将其强制转换为char指针并进行打印,则输出中只能看到8。

答案 1 :(得分:0)

这些不是upcasts和downcast,这意味着某种继承层次结构。

在第一个示例中,您将指向一个整数的指针,就像它是一个指向char的指针一样。递增指向int的指针会增加4,将指向char的指针递增1会增加1(假设32位整数和8位字符)。取消引用它们分别产生一个int和一个char。因此碎片成为字节。

在第二个示例中,您将名为sample的unsigned char变量视为指向int的指针,并取消引用它。您实际上是从0x08内存地址读取垃圾。我想你忘记了&amp ;.您还将一个1字节的char和一个4字节的int传递给第二个printf,而不是4 + 4个字节,这会混淆printf,从堆栈中读取的内容比您给出的多3个字节。巧合的是,第一次调用printf的ptrUint值的一部分。使用%c而不是%p应该修复它。

答案 2 :(得分:0)

其他答案已经解释了为什么你看到了你所看到的。

我将补充说,您的第二个示例依赖于未定义的行为。取消引用指向最初不是int *的数据的int无效。即:

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