簡體   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