简体   繁体   English

空指针类型转换

[英]void pointer typecasting

I was trying to understand void pointer typecasting in C. I wrote a program to try and create a segmentation fault, but I am not getting it. 我试图理解C语言中的void指针类型转换。我编写了一个程序来尝试创建分段错误,但没有得到。 Can someone please explain to me why 有人可以向我解释为什么

Code: 码:

#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;
} 

Output : 输出:

*(ptr)                           : 458998657
*(U32 *)(obj)                    : 25
*((U32 *)(obj) + 1)              : 3215085752
*(U32 *)((U32 *)(obj) + 1)       : 3215085752
*(ptr)                           : 3215085752

The way I see it only the 2nd printf is legal as all others are referring to some uninitialized random memory and should cause a seg fault 我认为只有第二个printf是合法的,因为所有其他都引用了一些未初始化的随机存储器,并且应该导致段错误

UB is funny like that- the behaviour is undefined, not guaranteed segfault. UB很有趣-这样的行为是不确定的,不能保证存在段错误。 The address of obj + 1 is probably some other spot on the stack which is allocated to your program anyway. obj + 1的地址可能是堆栈上的任何其他位置,无论如何都将其分配给您的程序。 To get an almost guaranteed segfault, just de-reference obj before it has ever been assigned. 要获得几乎保证的段错误,只需在分配obj之前取消引用即可。

 U32* ptr;
  printf("*(ptr)                           : %lu\n", *(ptr));

ptr is uninitialized so it is undefined behavior to dereference it, ptr未初始化,因此取消引用是不确定的行为,

  obj = &value;
  ptr = &value;
  ptr++;  
  printf("*(U32 *)(obj)                    : %lu\n", *(U32 *)(obj)); 

Ok, as long as obj is pointing to a valid U32 (and U32 has to be an unsigned long as you're using %lu as the printf format) 好的,只要obj指向有效的U32(并且U32必须是无符号的,只要您使用%lu作为printf格式)

  printf("*((U32 *)(obj) + 1)              : %lu\n", *((U32 *)(obj) + 1));   

You're trying to dereference a pointer that points one U32 past any valid location, so it's undefined behavior. 您试图取消引用指向任何有效位置后的一个U32的指针,因此它是未定义的行为。

  printf("*(U32 *)((U32 *)(obj) + 1)       : %lu\n", *(U32 *)((U32 *)(obj) + 1)); 

Same as above. 同上。

  printf("*(ptr)                           : %lu\n", *(ptr));

Since you incremented ptr , it points one U32 past anything valid, which leads to undefined behavior. 由于您增加了ptr ,因此它将U32指向任何有效值之后的U32,这将导致未定义的行为。

As your code does things that invokes undefined behavior , it's really hard and often impossible to reason about what is going to happen. 由于您的代码执行的操作会调用未定义的行为 ,因此很难推理,而且往往无法推理出将要发生的事情。 It's undefined. 它是未定义的。 Something unexpected could happen. 可能会发生意外情况。 Something bad could happen. 可能发生坏事。 Nothing bad could happen, and so on. 不会发生任何不良情况,依此类推。 Doing something in C that you should not do, does not mean it will segfault. 在C中做您不应该做的事情,并不意味着它会出现段错误。

ptr points to a valid object ( value ) but ptr++ does not point to an object. ptr指向有效的对象( value ),但ptr++并不指向对象。 So accessing the element *ptr after the pointer increment is undefined behavior. 因此,在指针增加后访问元素*ptr是未定义的行为。 printf of *ptr can display random data but can also crash your program. *ptr printf可以显示随机数据,但也会使程序崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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