繁体   English   中英

空指针类型转换

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM