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