指针向下倾斜
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()来避免这种垃圾值?你建议什么样的补救方法来消除垃圾价值?
答案 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