C++11中l(wèi)onglong超長(zhǎng)整型和nullptr初始化空指針
本文介紹 C++11 標(biāo)準(zhǔn)中新添加的 long long 超長(zhǎng)整型和 nullptr 初始化空指針。
1. C++11:long long 超長(zhǎng)整型
C++ 11 標(biāo)準(zhǔn)中,基于整數(shù)大小的考慮,共提供了如下表所示的這些數(shù)據(jù)類型。與此同時(shí),標(biāo)準(zhǔn)中還明確限定了各個(gè)數(shù)據(jù)類型最少占用的位數(shù)。
整數(shù)類型 | 等價(jià)類型 | C++11標(biāo)準(zhǔn)規(guī)定占用最少位數(shù) |
---|---|---|
short | short int(有符號(hào)短整型) | 至少 16 位(2 個(gè)字節(jié)) |
signed short | short int(有符號(hào)短整型) | 至少 16 位(2 個(gè)字節(jié)) |
signed short int | short int(有符號(hào)短整型) | 至少 16 位(2 個(gè)字節(jié)) |
unsigned short | unsigned short int(無(wú)符號(hào)短整型) | 至少 16 位(2 個(gè)字節(jié)) |
unsigned short int | unsigned short int(無(wú)符號(hào)短整型) | 至少 16 位(2 個(gè)字節(jié)) |
int | int(有符號(hào)整形) | 至少 16 位(2 個(gè)字節(jié)) |
signed | int(有符號(hào)整形) | 至少 16 位(2 個(gè)字節(jié)) |
signed int | int(有符號(hào)整形) | 至少 16 位(2 個(gè)字節(jié)) |
unsigned | unsigned int(無(wú)符號(hào)整形) | 至少 16 位(2 個(gè)字節(jié)) |
unsigned int | unsigned int(無(wú)符號(hào)整形) | 至少 16 位(2 個(gè)字節(jié)) |
long | long int(有符號(hào)長(zhǎng)整形) | 至少 32 位(4 個(gè)字節(jié)) |
long int | long int(有符號(hào)長(zhǎng)整形) | 至少 32 位(4 個(gè)字節(jié)) |
signed long | long int(有符號(hào)長(zhǎng)整形) | 至少 32 位(4 個(gè)字節(jié)) |
signed long int | long int(有符號(hào)長(zhǎng)整形) | 至少 32 位(4 個(gè)字節(jié)) |
unsigned long | unsigned long int(無(wú)符號(hào)長(zhǎng)整形) | 至少 32 位(4 個(gè)字節(jié)) |
unsigned long int | unsigned long int(無(wú)符號(hào)長(zhǎng)整形) | 至少 32 位(4 個(gè)字節(jié)) |
long long(C++11) | long long int(有符號(hào)超長(zhǎng)整形) | 至少 64 位(8 個(gè)字節(jié)) |
long long int(C++11) | long long int(有符號(hào)超長(zhǎng)整形) | 至少 64 位(8 個(gè)字節(jié)) |
signed long long(C++11) | long long int(有符號(hào)超長(zhǎng)整形) | 至少 64 位(8 個(gè)字節(jié)) |
signed long long int(C++11) | long long int(有符號(hào)超長(zhǎng)整形) | 至少 64 位(8 個(gè)字節(jié)) |
unsigned long long(C++11) | unsigned long long int(無(wú)符號(hào)超長(zhǎng)整型) | 至少 64 位(8 個(gè)字節(jié)) |
unsigned long long int(C++11) | unsigned long long int(無(wú)符號(hào)超長(zhǎng)整型) | 至少 64 位(8 個(gè)字節(jié)) |
C++11 標(biāo)準(zhǔn)規(guī)定,每種整數(shù)類型必須同時(shí)具備有符號(hào)(signed)和無(wú)符號(hào)(unsigned)兩種類型,且每種具體的有符號(hào)整形和無(wú)符號(hào)整形所占用的存儲(chǔ)空間(也就是位數(shù))必須相同。不過(guò)需要注意的是,C++11 標(biāo)準(zhǔn)中只限定了每種類型最少占用多少存儲(chǔ)空間,不同的平臺(tái)可以占用不同的存儲(chǔ)空間。
在上表羅列的這些數(shù)據(jù)類型中,long long 超長(zhǎng)整型是 C++ 11 標(biāo)準(zhǔn)新添加的。其實(shí)早在 1995 年,就有人提議將 long long 整形寫入 C++ 98 標(biāo)準(zhǔn),但被委員會(huì)拒絕了。而后 long long 整形被 C99 標(biāo)準(zhǔn)(C語(yǔ)言標(biāo)準(zhǔn)之一)采納,并逐漸被很多編譯器支持,于是 C++ 標(biāo)準(zhǔn)委員會(huì)重新決定將 long long 整形寫入 C++ 11 標(biāo)準(zhǔn)中。
如同 long 類型整數(shù)需明確標(biāo)注 "L" 或者 "l" 后綴一樣,要使用 long long 類型的整數(shù),也必須標(biāo)注對(duì)應(yīng)的后綴:
- 對(duì)于有符號(hào) long long 整形,后綴用 "LL" 或者 "ll" 標(biāo)識(shí)。例如,"10LL" 就表示有符號(hào)超長(zhǎng)整數(shù) 10;
- 對(duì)于無(wú)符號(hào) long long 整形,后綴用 "ULL"、"ull"、"Ull" 或者 "uLL" 標(biāo)識(shí)。例如,"10ULL" 就表示無(wú)符號(hào)超長(zhǎng)整數(shù) 10。
如果不添加任何標(biāo)識(shí),則所有的整數(shù)都會(huì)默認(rèn)為 int 類型。
對(duì)于 long long 類型來(lái)說(shuō),如果想了解當(dāng)前平臺(tái)上 long long 整形的取值范圍,可以使用<climits>
頭文件中與 long long 整形相關(guān)的 3 個(gè)宏,分別為 LLONG_MIN、LLONG_MAX 和 ULLONG_MIN:
1)LLONG_MIN:代表當(dāng)前平臺(tái)上最小的 long long 類型整數(shù);
2)LLONG_MAX:代表當(dāng)前平臺(tái)上最大的 long long 類型整數(shù);
3)ULLONG_MIN:代表當(dāng)前平臺(tái)上最大的 unsigned long long 類型整數(shù)(無(wú)符號(hào)超長(zhǎng)整型的最小值為 0)。
舉個(gè)例子:
#include <iostream> #include <iomanip> #include <climits> using namespace std; int main() { cout <<"long long最大值:" << LLONG_MIN <<" "<< hex << LLONG_MIN <<"\n"; cout << dec <<"long long最小值:" << LLONG_MAX << " " << hex << LLONG_MAX << "\n"; cout << dec << "unsigned long long最大值:" << ULLONG_MAX << " " << hex << ULLONG_MAX; return 0; }
程序執(zhí)行結(jié)果為(不唯一):
long long最大值:-9223372036854775808 8000000000000000 long long最小值:9223372036854775807 7fffffffffffffff unsigned long long最大值:18446744073709551615 ffffffffffffffff
此程序中,輸出了各最大值和最小值對(duì)應(yīng)的十六進(jìn)制,顯然在當(dāng)前平臺(tái)(Windows10 64位操作系統(tǒng))上,long long 超長(zhǎng)整型占用 64 位(也就是 16 個(gè)字節(jié))的存儲(chǔ)空間。
2. C++11:nullptr 初始化空指針
實(shí)際開(kāi)發(fā)中,避免產(chǎn)生“野指針”最有效的方法,就是在定義指針的同時(shí)完成初始化操作,即便該指針的指向尚未明確,也要將其初始化為空指針。
所謂“野指針”,又稱“懸掛指針”,指的是沒(méi)有明確指向的指針。野指針往往指向的是那些不可用的內(nèi)存區(qū)域,這就意味著像操作普通指針那樣使用野指針(例如 &p),極可能導(dǎo)致程序發(fā)生異常。
C++98/03 標(biāo)準(zhǔn)中,將一個(gè)指針初始化為空指針的方式有 2 種:
int *p = 0; int *p = NULL; //推薦使用
可以看到,我們可以將指針明確指向 0(0x0000 0000)這個(gè)內(nèi)存空間。一方面,明確指針的指向可以避免其成為野指針;另一方面,大多數(shù)操作系統(tǒng)都不允許用戶對(duì)地址為 0 的內(nèi)存空間執(zhí)行寫操作,若用戶在程序中嘗試修改其內(nèi)容,則程序運(yùn)行會(huì)直接報(bào)錯(cuò)。
相比第一種方式,我們更習(xí)慣將指針初始化為 NULL。值得一提的是,NULL 并不是 C++ 的關(guān)鍵字,它是 C++ 為我們事先定義好的一個(gè)宏,并且它的值往往就是字面量 0(#define NULL 0)。
C++ 中將 NULL 定義為字面常量 0,雖然能滿足大部分場(chǎng)景的需要,但個(gè)別情況下,它會(huì)導(dǎo)致程序的運(yùn)行和我們的預(yù)期不符。例如:
#include <iostream> using namespace std; void isnull(void *c){ cout << "void*c" << endl; } void isnull(int n){ cout << "int n" << endl; } int main() { isnull(0); isnull(NULL); return 0; }
程序執(zhí)行結(jié)果為:
int n
int n
對(duì)于 isnull(0) 來(lái)說(shuō),顯然它真正調(diào)用的是參數(shù)為整形的 isnull() 函數(shù);而對(duì)于 isnull(NULL),我們期望它實(shí)際調(diào)用的是參數(shù)為 void*c 的 isnull() 函數(shù),但觀察程序的執(zhí)行結(jié)果不難看出,并不符合我們的預(yù)期。
C++ 98/03 標(biāo)準(zhǔn)中,如果我們想令 isnull(NULL) 實(shí)際調(diào)用的是 isnull(void* c),就需要對(duì) NULL(或者 0)進(jìn)行強(qiáng)制類型轉(zhuǎn)換:
isnull( (void*)NULL ); isnull( (void*)0 );
如此,才會(huì)成功調(diào)用我們預(yù)期的函數(shù)。
由于 C++ 98 標(biāo)準(zhǔn)使用期間,NULL 已經(jīng)得到了廣泛的應(yīng)用,出于兼容性的考慮,C++11 標(biāo)準(zhǔn)并沒(méi)有對(duì) NULL 的宏定義做任何修改。為了修正 C++ 存在的這一 BUG,C++ 標(biāo)準(zhǔn)委員會(huì)最終決定另其爐灶,在 C++11 標(biāo)準(zhǔn)中引入一個(gè)新關(guān)鍵字,即 nullptr。
在使用 nullptr 之前,需保證自己使用的編譯器支持該關(guān)鍵字。以 Visual Studio 和 codeblocks 為例,前者早在 2010 版本就對(duì) C++ 11 標(biāo)準(zhǔn)中的部分特性提供了支持,其中就包括 nullptr;如果使用后者,則需將其 G++ 編譯器版本至少升級(jí)至 4.6.1(同時(shí)開(kāi)啟 -std=c++0x 編譯選項(xiàng))。
nullptr 是 nullptr_t 類型的右值常量,專用于初始化空類型指針。nullptr_t 是 C++11 新增加的數(shù)據(jù)類型,可稱為“指針空值類型”。也就是說(shuō),nullpter 僅是該類型的一個(gè)實(shí)例對(duì)象(已經(jīng)定義好,可以直接使用),如果需要我們完全定義出多個(gè)同 nullptr 完全一樣的實(shí)例對(duì)象。
值得一提的是,nullptr 可以被隱式轉(zhuǎn)換成任意的指針類型。舉個(gè)例子:
int * a1 = nullptr; char * a2 = nullptr; double * a3 = nullptr;
顯然,不同類型的指針變量都可以使用 nullptr 來(lái)初始化,編譯器分別將 nullptr 隱式轉(zhuǎn)換成 int*、char* 以及 double* 指針類型。
另外,通過(guò)將指針初始化為 nullptr,可以很好地解決 NULL 遺留的問(wèn)題,比如:
#include <iostream> using namespace std; void isnull(void *c){ cout << "void*c" << endl; } void isnull(int n){ cout << "int n" << endl; } int main() { isnull(NULL); isnull(nullptr); return 0; }
程序執(zhí)行結(jié)果為:
int n
void*c
借助執(zhí)行結(jié)果不難看出,由于 nullptr 無(wú)法隱式轉(zhuǎn)換為整形,而可以隱式匹配指針類型,因此執(zhí)行結(jié)果和我們的預(yù)期相符。
總之在 C++11 標(biāo)準(zhǔn)下,相比 NULL 和 0,使用 nullptr 初始化空指針可以令我們編寫的程序更加健壯。
到此這篇關(guān)于C++11:longlong超長(zhǎng)整型和nullptr初始化空指針的文章就介紹到這了,更多相關(guān)C++11 nullptr初始化空指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++設(shè)計(jì)模式中控制反轉(zhuǎn)與依賴注入淺析
這篇文章主要介紹了C++設(shè)計(jì)模式中控制反轉(zhuǎn)與依賴注入,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-01-01解析C++的線性表鏈?zhǔn)酱鎯?chǔ)設(shè)計(jì)與相關(guān)的API實(shí)現(xiàn)
這篇文章主要介紹了解析C++中的線性表鏈?zhǔn)酱鎯?chǔ)設(shè)計(jì)與相關(guān)的API實(shí)現(xiàn),文中的實(shí)例很好地體現(xiàn)了如何創(chuàng)建和遍歷鏈表等基本操作,需要的朋友可以參考下2016-03-03C語(yǔ)言編程PAT乙級(jí)學(xué)習(xí)筆記示例分享
這篇文章主要為大家介紹了C語(yǔ)言編程PAT乙級(jí)學(xué)習(xí)筆記實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05C語(yǔ)言詳細(xì)分析不同類型數(shù)據(jù)在內(nèi)存中的存儲(chǔ)
使用編程語(yǔ)言進(jìn)行編程時(shí),需要用到各種變量來(lái)存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來(lái)分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么2022-08-08數(shù)據(jù)結(jié)構(gòu)之矩陣行列和相等的實(shí)例
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)之矩陣行列和相等的實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10C++實(shí)現(xiàn)二分法求連續(xù)一元函數(shù)根
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)二分法求連續(xù)一元函數(shù)根,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06