1

指针向下转换

    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() 来避免这个垃圾值?你会建议什么样的补救措施来删除垃圾值?

4

3 回答 3

1

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

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

于 2011-07-03T07:29:38.483 回答
0

这些不是向上转换和向下转换,这意味着某种继承层次结构。

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

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

于 2011-07-03T07:48:13.710 回答
0

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

我要补充一点,您的第二个示例依赖于未定义的行为。取消引用int *指向最初不是int. IE:

char x = 5;
int *p = (int *)&x;
printf("%d\n", *p);  // undefined behaviour
于 2011-07-03T11:07:08.570 回答