[英]void pointer typecasting
我试图理解C语言中的void指针类型转换。我编写了一个程序来尝试创建分段错误,但没有得到。 有人可以向我解释为什么
码:
#include <stdio.h>
typedef unsigned long U32;
int main()
{
void *obj;
U32 value = 25;
U32* ptr;
printf("*(ptr) : %lu\n", *(ptr));
obj = &value;
ptr = &value;
ptr++;
printf("*(U32 *)(obj) : %lu\n", *(U32 *)(obj));
printf("*((U32 *)(obj) + 1) : %lu\n", *((U32 *)(obj) + 1));
printf("*(U32 *)((U32 *)(obj) + 1) : %lu\n", *(U32 *)((U32 *)(obj) + 1));
printf("*(ptr) : %lu\n", *(ptr));
return 0;
}
输出:
*(ptr) : 458998657
*(U32 *)(obj) : 25
*((U32 *)(obj) + 1) : 3215085752
*(U32 *)((U32 *)(obj) + 1) : 3215085752
*(ptr) : 3215085752
我认为只有第二个printf是合法的,因为所有其他都引用了一些未初始化的随机存储器,并且应该导致段错误
UB很有趣-这样的行为是不确定的,不能保证存在段错误。 obj + 1
的地址可能是堆栈上的任何其他位置,无论如何都将其分配给您的程序。 要获得几乎保证的段错误,只需在分配obj
之前取消引用即可。
U32* ptr;
printf("*(ptr) : %lu\n", *(ptr));
ptr
未初始化,因此取消引用是不确定的行为,
obj = &value;
ptr = &value;
ptr++;
printf("*(U32 *)(obj) : %lu\n", *(U32 *)(obj));
好的,只要obj
指向有效的U32(并且U32必须是无符号的,只要您使用%lu作为printf格式)
printf("*((U32 *)(obj) + 1) : %lu\n", *((U32 *)(obj) + 1));
您试图取消引用指向任何有效位置后的一个U32的指针,因此它是未定义的行为。
printf("*(U32 *)((U32 *)(obj) + 1) : %lu\n", *(U32 *)((U32 *)(obj) + 1));
同上。
printf("*(ptr) : %lu\n", *(ptr));
由于您增加了ptr
,因此它将U32指向任何有效值之后的U32,这将导致未定义的行为。
由于您的代码执行的操作会调用未定义的行为 ,因此很难推理,而且往往无法推理出将要发生的事情。 它是未定义的。 可能会发生意外情况。 可能发生坏事。 不会发生任何不良情况,依此类推。 在C中做您不应该做的事情,并不意味着它会出现段错误。
ptr
指向有效的对象( value
),但ptr++
并不指向对象。 因此,在指针增加后访问元素*ptr
是未定义的行为。 *ptr
printf
可以显示随机数据,但也会使程序崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.