C++11中longlong超長整型和nullptr初始化空指針
本文介紹 C++11 標準中新添加的 long long 超長整型和 nullptr 初始化空指針。
1. C++11:long long 超長整型
C++ 11 標準中,基於整數大小的考慮,共提供瞭如下表所示的這些數據類型。與此同時,標準中還明確限定瞭各個數據類型最少占用的位數。
整數類型 | 等價類型 | C++11標準規定占用最少位數 |
---|---|---|
short | short int(有符號短整型) | 至少 16 位(2 個字節) |
signed short | short int(有符號短整型) | 至少 16 位(2 個字節) |
signed short int | short int(有符號短整型) | 至少 16 位(2 個字節) |
unsigned short | unsigned short int(無符號短整型) | 至少 16 位(2 個字節) |
unsigned short int | unsigned short int(無符號短整型) | 至少 16 位(2 個字節) |
int | int(有符號整形) | 至少 16 位(2 個字節) |
signed | int(有符號整形) | 至少 16 位(2 個字節) |
signed int | int(有符號整形) | 至少 16 位(2 個字節) |
unsigned | unsigned int(無符號整形) | 至少 16 位(2 個字節) |
unsigned int | unsigned int(無符號整形) | 至少 16 位(2 個字節) |
long | long int(有符號長整形) | 至少 32 位(4 個字節) |
long int | long int(有符號長整形) | 至少 32 位(4 個字節) |
signed long | long int(有符號長整形) | 至少 32 位(4 個字節) |
signed long int | long int(有符號長整形) | 至少 32 位(4 個字節) |
unsigned long | unsigned long int(無符號長整形) | 至少 32 位(4 個字節) |
unsigned long int | unsigned long int(無符號長整形) | 至少 32 位(4 個字節) |
long long(C++11) | long long int(有符號超長整形) | 至少 64 位(8 個字節) |
long long int(C++11) | long long int(有符號超長整形) | 至少 64 位(8 個字節) |
signed long long(C++11) | long long int(有符號超長整形) | 至少 64 位(8 個字節) |
signed long long int(C++11) | long long int(有符號超長整形) | 至少 64 位(8 個字節) |
unsigned long long(C++11) | unsigned long long int(無符號超長整型) | 至少 64 位(8 個字節) |
unsigned long long int(C++11) | unsigned long long int(無符號超長整型) | 至少 64 位(8 個字節) |
C++11 標準規定,每種整數類型必須同時具備有符號(signed)和無符號(unsigned)兩種類型,且每種具體的有符號整形和無符號整形所占用的存儲空間(也就是位數)必須相同。不過需要註意的是,C++11 標準中隻限定瞭每種類型最少占用多少存儲空間,不同的平臺可以占用不同的存儲空間。
在上表羅列的這些數據類型中,long long 超長整型是 C++ 11 標準新添加的。其實早在 1995 年,就有人提議將 long long 整形寫入 C++ 98 標準,但被委員會拒絕瞭。而後 long long 整形被 C99 標準(C語言標準之一)采納,並逐漸被很多編譯器支持,於是 C++ 標準委員會重新決定將 long long 整形寫入 C++ 11 標準中。
如同 long 類型整數需明確標註 "L" 或者 "l" 後綴一樣,要使用 long long 類型的整數,也必須標註對應的後綴:
- 對於有符號 long long 整形,後綴用 "LL" 或者 "ll" 標識。例如,"10LL" 就表示有符號超長整數 10;
- 對於無符號 long long 整形,後綴用 "ULL"、"ull"、"Ull" 或者 "uLL" 標識。例如,"10ULL" 就表示無符號超長整數 10。
如果不添加任何標識,則所有的整數都會默認為 int 類型。
對於 long long 類型來說,如果想瞭解當前平臺上 long long 整形的取值范圍,可以使用<climits>
頭文件中與 long long 整形相關的 3 個宏,分別為 LLONG_MIN、LLONG_MAX 和 ULLONG_MIN:
1)LLONG_MIN:代表當前平臺上最小的 long long 類型整數;
2)LLONG_MAX:代表當前平臺上最大的 long long 類型整數;
3)ULLONG_MIN:代表當前平臺上最大的 unsigned long long 類型整數(無符號超長整型的最小值為 0)。
舉個例子:
#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; }
程序執行結果為(不唯一):
long long最大值:-9223372036854775808 8000000000000000 long long最小值:9223372036854775807 7fffffffffffffff unsigned long long最大值:18446744073709551615 ffffffffffffffff
此程序中,輸出瞭各最大值和最小值對應的十六進制,顯然在當前平臺(Windows10 64位操作系統)上,long long 超長整型占用 64 位(也就是 16 個字節)的存儲空間。
2. C++11:nullptr 初始化空指針
實際開發中,避免產生“野指針”最有效的方法,就是在定義指針的同時完成初始化操作,即便該指針的指向尚未明確,也要將其初始化為空指針。
所謂“野指針”,又稱“懸掛指針”,指的是沒有明確指向的指針。野指針往往指向的是那些不可用的內存區域,這就意味著像操作普通指針那樣使用野指針(例如 &p),極可能導致程序發生異常。
C++98/03 標準中,將一個指針初始化為空指針的方式有 2 種:
int *p = 0; int *p = NULL; //推薦使用
可以看到,我們可以將指針明確指向 0(0x0000 0000)這個內存空間。一方面,明確指針的指向可以避免其成為野指針;另一方面,大多數操作系統都不允許用戶對地址為 0 的內存空間執行寫操作,若用戶在程序中嘗試修改其內容,則程序運行會直接報錯。
相比第一種方式,我們更習慣將指針初始化為 NULL。值得一提的是,NULL 並不是 C++ 的關鍵字,它是 C++ 為我們事先定義好的一個宏,並且它的值往往就是字面量 0(#define NULL 0)。
C++ 中將 NULL 定義為字面常量 0,雖然能滿足大部分場景的需要,但個別情況下,它會導致程序的運行和我們的預期不符。例如:
#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; }
程序執行結果為:
int n
int n
對於 isnull(0) 來說,顯然它真正調用的是參數為整形的 isnull() 函數;而對於 isnull(NULL),我們期望它實際調用的是參數為 void*c 的 isnull() 函數,但觀察程序的執行結果不難看出,並不符合我們的預期。
C++ 98/03 標準中,如果我們想令 isnull(NULL) 實際調用的是 isnull(void* c),就需要對 NULL(或者 0)進行強制類型轉換:
isnull( (void*)NULL ); isnull( (void*)0 );
如此,才會成功調用我們預期的函數。
由於 C++ 98 標準使用期間,NULL 已經得到瞭廣泛的應用,出於兼容性的考慮,C++11 標準並沒有對 NULL 的宏定義做任何修改。為瞭修正 C++ 存在的這一 BUG,C++ 標準委員會最終決定另其爐灶,在 C++11 標準中引入一個新關鍵字,即 nullptr。
在使用 nullptr 之前,需保證自己使用的編譯器支持該關鍵字。以 Visual Studio 和 codeblocks 為例,前者早在 2010 版本就對 C++ 11 標準中的部分特性提供瞭支持,其中就包括 nullptr;如果使用後者,則需將其 G++ 編譯器版本至少升級至 4.6.1(同時開啟 -std=c++0x 編譯選項)。
nullptr 是 nullptr_t 類型的右值常量,專用於初始化空類型指針。nullptr_t 是 C++11 新增加的數據類型,可稱為“指針空值類型”。也就是說,nullpter 僅是該類型的一個實例對象(已經定義好,可以直接使用),如果需要我們完全定義出多個同 nullptr 完全一樣的實例對象。
值得一提的是,nullptr 可以被隱式轉換成任意的指針類型。舉個例子:
int * a1 = nullptr; char * a2 = nullptr; double * a3 = nullptr;
顯然,不同類型的指針變量都可以使用 nullptr 來初始化,編譯器分別將 nullptr 隱式轉換成 int*、char* 以及 double* 指針類型。
另外,通過將指針初始化為 nullptr,可以很好地解決 NULL 遺留的問題,比如:
#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; }
程序執行結果為:
int n
void*c
借助執行結果不難看出,由於 nullptr 無法隱式轉換為整形,而可以隱式匹配指針類型,因此執行結果和我們的預期相符。
總之在 C++11 標準下,相比 NULL 和 0,使用 nullptr 初始化空指針可以令我們編寫的程序更加健壯。
到此這篇關於C++11:longlong超長整型和nullptr初始化空指針的文章就介紹到這瞭,更多相關C++11 nullptr初始化空指針內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++ 中的INT_MAX,INT_MIN數值大小操作
- 一篇文章帶你瞭解C++Primer學習日記–處理數據
- C++ 數據類型強制轉化的實現
- C++ 程序流程結構詳解
- C++中signed main和int main的區別