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

當前位置:首頁 > > strongerHuang
[導讀]指針算是一個比較常見,也是比較重要的知識點,大部分人都只是停留在表面的認識,今天轉載逍遙整理的一篇文章,通俗易懂的描述了關于指針相關的內容。




關注、星標公眾,不錯過精彩內容

作者:李肖遙
ID:技術讓夢想更偉大

指針算是一個比較常見,也是比較重要的知識點,大部分人都只是停留在表面的認識,今天轉載逍遙整理的一篇文章,通俗易懂的描述了關于指針相關的內容。


NULL在C/C++中的標準定義

NULL的標準定義

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

編譯器預先定義了一個宏_cplusplus,來判斷當前的編譯環(huán)境是C++的還是C語言的,在C++定義為0,在C語言中定義為(void *)0。

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

在C語言中,C中的“標準”寫法,NULL被替換為一個void* 類型的指針右值,值等于0;由于是void* 類型,可以隱式轉化為其它類型的指針。

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

NULL 的本質是什么

我們從指針,空指針,空指針常量以及指向的內存說起

從指針角度來看

我們看以下定義,p是一個函數內的局部變量,則p的值是隨機的,也就是說p是一個野指針。

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

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

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

什么是空指針(null pointer)?

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

定義char *p=0后,在之后p的任何一種賦值操作之后,p 都成為一個空指針,即p不指向任何實際的對象或者函數。反過來說,任何對象或者函數的地址都不可能是空指針。

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

值為0的整數常量表達式,或強制轉換為void *類型的表達式,稱為空指針常量

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

這里標準沒有定義,取決于系統(tǒng)的實現。我們常見的空指針一般指向0x00000000地址,即空指針的內部用全0x00000000來表示,也有一些系統(tǒng)用一些特殊的地址值或者特殊的方式表示空指針。

在我們實際寫代碼時,關鍵點在于判斷哪個是空指針。

NULL 有什么作用

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

當你嘗試訪問的時候會阻止你,但是有些地址不是只讀的,如果一個指針指向了這個地址,你又在不經意間修改了它,可能會導致一些重要的文件被修改,所以指針初始化成NULL是有必要的。

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

  • '\0'是一個轉義字符,他對應的ASCII編碼值是0,本質就是0;常用于表示字符串的結尾標志,以判斷字符串有沒有到頭。
  • '0'是一個字符,他對應的ASCII編碼值是48,本質是48。
  • 0是一個int類型的數字,本質就是0。
  • NULL是一個表達式,是強制類型轉換為 void *類型的0,一般用來比較指針是否是一個野指針。

NULL是不是0呢

NULL 就是0?

我們先來看以下代碼:

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

結果如下:

輸出(null) ,在執(zhí)行int *p=NULL,打印出來空白,實際上p的值為0x00000000,在C語言中,NULL的本質是0,但是這個0不是當一個整形數據來解析,而是當一個內存地址來解析的,代表的是內存的0地址。

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

NULL 不是0?

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

//https://tool.lu/coderunner/
//來源:技術讓夢想更偉大
//作者:李肖遙
#include
int?main()
{????
?
?int?*node?=?NULL;
?int?p?=?0;
?p?=?*node;
?printf("%d\n",p);
?
?return?0;
}

編譯結果如下:

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

那么看到這里你覺得NULL還是0嗎?根據宏定義我們知道:(void *)0表示把數值0強制轉換為void *類型,所以最后運行結果為0。

變量在定義時,系統(tǒng)會給他分配內存空間,指針變量也是一樣,如果指針沒有指向的話,那么地址就是隨機值,如果不小心用的話就會導致數據錯誤,從而使程序退出。

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

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

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

//https://tool.lu/coderunner/
//來源:技術讓夢想更偉大
//作者:李肖遙
#include?

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

輸出結果如下:

vPassByFun函數是值傳遞,node指針變量的值并不受影響,所以這個程序的效果和上一個程序運行結果都是段錯誤。

如果要讓結果為1024,應該怎樣寫代碼呢?我們來這樣寫代碼:

//https://tool.lu/coderunner/
//來源:技術讓夢想更偉大
//作者:李肖遙
#include?

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;

}

運行結果如下:

傳遞一個二級指針也就是傳遞node指針變量的指針給vPassByFun函數,這樣的話結果就對了。

最后

編碼過程中,我們需要對自己的指針負責,往往導致bug出現或者找不到問題所在地的就是這種細節(jié)。

推薦閱讀:

基于STM32的Keil、IAR仿真打印輸出

快速理解STM32位帶操作原理和用途

Linux 內核的 100% 自由版本 GNU Linux-libre 5.8 發(fā)布


關注 微信公眾號『strongerHuang』,后臺回復“1024”查看更多內容,回復“加群”按規(guī)則加入技術交流群。


長按前往圖中包含的公眾號關注

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

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