日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > > 小麥大叔
[導(dǎo)讀]關(guān)注、星標(biāo)公眾號(hào) ,直達(dá)精彩內(nèi)容 ID:技術(shù)讓夢(mèng)想更偉大 作者:李肖遙 面試官:滿頭的汗的,來(lái)面試的路一定很遠(yuǎn)吧? 還好還好,騎車不到倆小時(shí) 面試官:來(lái)先喝杯水,咱們面試不急,邊喝邊聊 哇,謝謝您啦,咕隆咕隆喝下半杯 面試官:那咱們開(kāi)始吧,看你項(xiàng)目做




關(guān)注、星標(biāo)公眾號(hào) ,直達(dá)精彩內(nèi)容

ID:技術(shù)讓夢(mèng)想更偉大

作者:李肖遙


面試官:滿頭的汗的,來(lái)面試的路一定很遠(yuǎn)吧?


還好還好,騎車不到倆小時(shí)


面試官:來(lái)先喝杯水,咱們面試不急,邊喝邊聊


哇,謝謝您啦,咕隆咕隆喝下半杯


面試官:那咱們開(kāi)始吧,看你項(xiàng)目做的還不少啊,不錯(cuò)不錯(cuò),咱們隨便聊聊。


哇,“這面試官還不錯(cuò),感覺(jué)有戲”


面試官:說(shuō)說(shuō)空指針NULL是本質(zhì)什么,與0一樣嗎


嗯嗯,這個(gè),NULL不就是0嗎?

 

面試官:你確定是嗎,面帶微笑,淡定的眼神......


嗯嗯,應(yīng)該是吧,,,不是吧,汗又開(kāi)始冒起了來(lái)了......



面試官:嗯嗯,了解了,不急慢慢喝水,我先上個(gè)廁所。


水的滋潤(rùn)與口水相互交織,騎車兩小時(shí),面試3分鐘,這次我哉在這里了。

 



NULL在C/C++中的標(biāo)準(zhǔn)定義

NULL的標(biāo)準(zhǔn)定義

#if !defined(NULL) && defined(__NEEDS_NULL)
#ifdef _cplusplus      
#define NULL 0         // 這里對(duì)應(yīng)C++的情況
#else
#define NULL (void *)0 // 這里對(duì)應(yīng)C語(yǔ)言的情況
#endif

編譯器預(yù)先定義了一個(gè)宏_cplusplus,來(lái)判斷當(dāng)前的編譯環(huán)境是C++的還是C語(yǔ)言的,在C++定義為0,在C語(yǔ)言中定義為(void *)0。

在C/C++中的區(qū)別

在C語(yǔ)言中,C中的“標(biāo)準(zhǔn)”寫(xiě)法,NULL被替換為一個(gè)void* 類型的指針右值,值等于0;由于是void* 類型,可以隱式轉(zhuǎn)化為其它類型的指針。

在C++中,void* 無(wú)法自由隱式轉(zhuǎn)換為其它類型的指針,而字面量0可以隱式轉(zhuǎn)換為指針類型。

NULL 的本質(zhì)是什么

我們從指針,空指針,空指針常量以及指向的內(nèi)存說(shuō)起

從指針角度來(lái)看

我們看以下定義,p是一個(gè)函數(shù)內(nèi)的局部變量,則p的值是隨機(jī)的,也就是說(shuō)p是一個(gè)野指針。

int func()
{
  int *p; 
  ...
}

再看以下函數(shù),p是一個(gè)局部變量,分配在棧上的地址,p的值是(void *)0,實(shí)際就是0x00000000,意思就是指針p指向內(nèi)存的0x00000000地址處。這時(shí)候p就不是野指針了。

int func()
{
  int *p = NULL; 
  ...
}

什么是空指針(null pointer)?

如果將空指針常量轉(zhuǎn)換為指針類型,則保證生成的指針(稱為空指針)將不相等的值與指向任何對(duì)象或函數(shù)的指針進(jìn)行比較。

定義char *p=0后,在之后p的任何一種賦值操作之后,p 都成為一個(gè)空指針,即p不指向任何實(shí)際的對(duì)象或者函數(shù)。反過(guò)來(lái)說(shuō),任何對(duì)象或者函數(shù)的地址都不可能是空指針。

什么是空指針常量(null pointer constant)?

值為0的整數(shù)常量表達(dá)式,或強(qiáng)制轉(zhuǎn)換為void *類型的表達(dá)式,稱為空指針常量

空指針(null pointer)指向了哪里的內(nèi)存

這里標(biāo)準(zhǔn)沒(méi)有定義,取決于系統(tǒng)的實(shí)現(xiàn)。我們常見(jiàn)的空指針一般指向0x00000000地址,即空指針的內(nèi)部用全0x00000000來(lái)表示,也有一些系統(tǒng)用一些特殊的地址值或者特殊的方式表示空指針。

在我們實(shí)際寫(xiě)代碼時(shí),關(guān)鍵點(diǎn)在于判斷哪個(gè)是空指針。

NULL 有什么作用

在大部分的CPU中,內(nèi)存的0x00000000地址處都不是可以隨便訪問(wèn)的,所以野指針指向了這個(gè)區(qū)域可以保證野指針有個(gè)安家之所,否則會(huì)發(fā)生段錯(cuò)誤。

當(dāng)你嘗試訪問(wèn)的時(shí)候會(huì)阻止你,但是有些地址不是只讀的,如果一個(gè)指針指向了這個(gè)地址,你又在不經(jīng)意間修改了它,可能會(huì)導(dǎo)致一些重要的文件被修改,所以指針初始化成NULL是有必要的。

注意不要混用'\0' 和 '0' 和 0  和 NULL

  • '\0'是一個(gè)轉(zhuǎn)義字符,他對(duì)應(yīng)的ASCII編碼值是0,本質(zhì)就是0;常用于表示字符串的結(jié)尾標(biāo)志,以判斷字符串有沒(méi)有到頭。
  • '0'是一個(gè)字符,他對(duì)應(yīng)的ASCII編碼值是48,本質(zhì)是48。
  • 0是一個(gè)int類型的數(shù)字,本質(zhì)就是0。
  • NULL是一個(gè)表達(dá)式,是強(qiáng)制類型轉(zhuǎn)換為 void *類型的0,一般用來(lái)比較指針是否是一個(gè)野指針。

NULL是不是0呢

NULL 就是0?

我們先來(lái)看以下代碼:

//https://tool.lu/coderunner/
#include<stdio.h>
int main()
{    
  int *p=NULL;    
  printf("%s",p); 
}

結(jié)果如下:

輸出(null) ,在執(zhí)行int *p=NULL,打印出來(lái)空白,實(shí)際上p的值為0x00000000,在C語(yǔ)言中,NULL的本質(zhì)是0,但是這個(gè)0不是當(dāng)一個(gè)整形數(shù)據(jù)來(lái)解析,而是當(dāng)一個(gè)內(nèi)存地址來(lái)解析的,代表的是內(nèi)存的0地址。

(void *)0這個(gè)整體表達(dá)式表示一個(gè)指針,地址在哪里取決于指針變量本身,這個(gè)指針變量指向0地址(實(shí)際是0地址開(kāi)始的一段內(nèi)存)。

NULL 不是0?

如果一個(gè)指針被賦予NULL,相當(dāng)于這個(gè)指針執(zhí)行了0x00000000這個(gè)邏輯地址,但是在C語(yǔ)言中0x0000這個(gè)邏輯地址用戶是不能使用的,所以當(dāng)你試圖取一個(gè)指向了NULL的指針的內(nèi)容時(shí),就會(huì)提示段錯(cuò)誤,測(cè)試一下代碼如下:

//https://tool.lu/coderunner/
//來(lái)源:技術(shù)讓夢(mèng)想更偉大
//作者:李肖遙
#include<stdio.h>
int main()
{    
 
 int *node = NULL;
 int p = 0;
 p = *node;
 printf("%d\n",p);
 
 return 0;
}

編譯結(jié)果如下:

由于指針node執(zhí)行的是NULL,也就是邏輯地址0x00000000,而這個(gè)地址不能訪問(wèn),所以編譯器提示段錯(cuò)誤。

那么看到這里你覺(jué)得NULL還是0嗎?根據(jù)宏定義我們知道:(void *)0表示把數(shù)值0強(qiáng)制轉(zhuǎn)換為void *類型,所以最后運(yùn)行結(jié)果為0。

變量在定義時(shí),系統(tǒng)會(huì)給他分配內(nèi)存空間,指針變量也是一樣,如果指針沒(méi)有指向的話,那么地址就是隨機(jī)值,如果不小心用的話就會(huì)導(dǎo)致數(shù)據(jù)錯(cuò)誤,從而使程序退出。

NULL 使指針p指向地址0x00000000,在大多數(shù)系統(tǒng)中都將0x00000000作為不被使用的地址,所以運(yùn)用p也不會(huì)毀壞數(shù)據(jù)。

但也有系統(tǒng)會(huì)使用地址0x00000000,而將 NULL 定義為其他值,所以不要把 NULL 和 0 等同起來(lái)。

我們使用值傳遞的方式來(lái)看,在網(wǎng)上有一個(gè)面試題,這里我參考一下代碼,能夠幫助大家更好的理解,其代碼如下:

//https://tool.lu/coderunner/
//來(lái)源:技術(shù)讓夢(mèng)想更偉大
//作者:李肖遙
#include <stdio.h>

void vPassByFun(int *node)
{
    static int N = 1024;
    node = &N;
}

int main()
{
 
    int *node = NULL;
    int p = 0;
    vPassByFun(node);
    p = *node;
 
    printf("%d\n",p);
    
    return 0;
}

輸出結(jié)果如下:

vPassByFun函數(shù)是值傳遞,node指針變量的值并不受影響,所以這個(gè)程序的效果和上一個(gè)程序運(yùn)行結(jié)果都是段錯(cuò)誤。

如果要讓結(jié)果為1024,應(yīng)該怎樣寫(xiě)代碼呢?我們來(lái)這樣寫(xiě)代碼:

//https://tool.lu/coderunner/
//來(lái)源:技術(shù)讓夢(mèng)想更偉大
//作者:李肖遙
#include <stdio.h>

void vPassByFun(int ** node)
{
    static int N = 1024;
    *node=&N;
}

int main()
{
 
    int *node = NULL;
    int p = 0;

    vPassByFun(&node);
    p = *node;

    printf("%d\n",p);
 
    return 0;

}

運(yùn)行結(jié)果如下:

傳遞一個(gè)二級(jí)指針也就是傳遞node指針變量的指針給vPassByFun函數(shù),這樣的話結(jié)果就對(duì)了。

最后

編碼過(guò)程中,我們需要對(duì)自己的指針負(fù)責(zé),往往導(dǎo)致bug出現(xiàn)或者找不到問(wèn)題所在地的就是這種細(xì)節(jié)。最后,原創(chuàng)不易,希望能夠改正文章的錯(cuò)誤,多提意見(jiàn)留言,謝謝。

推薦閱讀:


    
             
嵌入式編程專輯
Linux 學(xué)習(xí)專輯
C/C++編程專輯

關(guān)注 微信公眾號(hào)『技術(shù)讓夢(mèng)想更偉大』,后臺(tái)回復(fù)“ m ”查看更多內(nèi)容,回復(fù)“ 加群 ”加入技術(shù)交流群。

長(zhǎng)按前往圖中包含的公眾號(hào)關(guān)注

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉