日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

64位环境0和NULL的区别

發(fā)布時間:2024/1/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 64位环境0和NULL的区别 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

0 & NULL

? ? 在C語言中將值為0的指針作為NULL,NULL通常被定義為0或((void *)0);

有很多應該使用NULL的地方寫0代替的程序,通常這樣的寫法也不會發(fā)生問題,如:

? char *p = 0;

? if (p != 0) ...

此時p為char *,進行運算前,會將操作數(shù)類型轉換為與之有互換性的某個類型上,所以默認int型的0轉換為char *型的NULL,這樣一來,下面的書寫方法也沒有問題:

? if (p)

在此時if會用布爾值來判斷,用表達式的布爾值是否為0來判斷。如下所示:

? if (p != 0)

相反的條件

? if (!p)

也跟

?if(p == 0)

等價

象這樣在多數(shù)情況下,用0代替NULL的處理方式也可以。但是也存在不通用的地方。

?

0和NULL不同的情況

? 如前所述,NULL并不是int型的0值,而是指針型的0值(值為0的指針);也就是說編譯器必須要明白是用指針理性來解釋,

在x86那樣的ILP32環(huán)境中由于int long指針都是32位,所以int型的0可以等同于指針的NULL。但在IA64那樣的LP64環(huán)境中int仍然是32位的,但long和指針都是64位的,int的0便不等同于NULL了。使用可變長參數(shù)時,這個問題很明顯。示例代碼:

struct s *foo(const char *name, ...) {va_list va;struct s *sp;char *p;va_start(va, fmt);sp = (struct s *)malloc(*sp);if (!sp) {return 0;}memset(sp, 0,sizeof(*sp));set_name(sp, name);while ((p = va_arg(va, char *))) {set_item(sp, p);}return sp; }... sp = foo("foo", "bar", 0); ...

這里的foo()是取得可變長參數(shù)后,利用name這個名稱和剩下的參數(shù)表初始化item結構體的函數(shù)。這個代碼在LP64環(huán)境下不能正常運行。

調用foo("foo", "bar", 0)之后,參數(shù)會像下面這樣 堆積在棧上:

? ? 為0的int

? ? 指向"bar"的const char *

? ? 指向"foo"的const char *

在foo()運行時,形參const char *name指向第一個參數(shù)"foo", 其他變參通過va_list來訪問,在foo()中通過如下形式取va_list內容:

p = va_arg(va, char *);

也就是參數(shù)作為char *來取出,第一個是指向"bar"的指針,所以沒問題。而第二個變參傳的是int型(32位)的0,但讀取時是按64位的char *來取的,多讀取了4字節(jié)為初始化的內存數(shù)據(jù),如果這四個字節(jié)不是全0,而導致進入下一次while循環(huán),會發(fā)生什么后果呢?

這就是將0和NULL混用而導致的bug,正確調用foo()的方法:

sp = foo("foo", "bar", NULL);

也有自己編程使用類似函數(shù)的情況,例如:使用類似機制的execl(3)時,必須用NULL來終止參數(shù)列表(見man手冊提示):

int execl(const char *path, const char *arg, .../*, (char *)0*/);

字面量 0 ,是int型,在64位系統(tǒng)里是32位。
宏 NULL, 定義為((void*)0),在64位系統(tǒng)里是64位。

在foo函數(shù)定義之后使用該函數(shù),或在使用foo函數(shù)之前聲明一下foo函數(shù),編譯器就會自動將int型的0轉為void*型的NULL。

如果沒有定義或聲明foo函數(shù)就直接使用foo函數(shù),編譯器會根據(jù)你傳入的參數(shù)產(chǎn)生一個隱含的聲明。
調用foo("foo", "bar", 0),編譯器會認為你的函數(shù)聲明為int foo(char*, char*, int),并且根據(jù)此聲明壓棧,共20字節(jié)。

而函數(shù)實際定義為foo(char*, char *, void*),函數(shù)會把傳入的第三個參數(shù)當做void*解析,16~19字節(jié)是整數(shù)0,20~23字節(jié)數(shù)據(jù)未定義,函數(shù)會取到一個錯誤的指針(在big-endian系統(tǒng)里,指針低位部分為0,高位部分未定義,即0x********00000000;在little-endian系統(tǒng)里,指針低位部分未定義,高位部分位0,即0x00000000********)

C++中還可以用nullptr。

?

轉自:https://www.phpfans.net/ask/MTEwNjM3OQ.html

總結

以上是生活随笔為你收集整理的64位环境0和NULL的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。