C++11:longlong超長整型和nullptr初始化空指針

来源:https://www.cnblogs.com/crossoverpptx/archive/2022/12/31/17016228.html
-Advertisement-
Play Games

本文介紹 C++11 標準中新添加的 long long 超長整型和 nullptr 初始化空指針。 1. C++11:long long 超長整型 C++ 11 標準中,基於整數大小的考慮,共提供瞭如下表所示的這些數據類型。與此同時,標準中還明確限定了各個數據類型最少占用的位數。 | 整數類型 | ...


本文介紹 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 初始化空指針可以令我們編寫的程式更加健壯。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HttpClient 版本已經到 5.2.1 了. 在版本4中的一些方法已經變成 deprecated, 於是將之前的工具類升級一下, 順便把中間遇到的問題記錄一下 ...
  • 一、註冊流程 單nacos節點流程圖如下: 流程圖可以知,Nacos註冊流程包括客戶端的服務註冊、服務實例列表拉取、定時心跳任務;以及服務端的定時檢查服務實例任務、服務實例更新推送5個功能。 服務註冊:當客戶端啟動的時候會根據當前微服務的配置信息把微服務註冊到nacos服務端。 服務實例列表拉取:當 ...
  • 家居網購項目實現011 以下皆為部分代碼,詳見 https://github.com/liyuelian/furniture_mall.git 27.功能25-事務管理 27.1下訂單問題思考 在生成訂單的功能中,系統會去同時修改資料庫中的order,order_item,furn三張表,如果有任意 ...
  • 前言 在系統運行過程中,可能由於一些配置項的簡單變動需要重新打包啟停項目,這對於在運行中的項目會造成數據丟失,客戶操作無響應等情況發生,針對這類情況對開發框架進行升級提供yml文件實時修改更新功能 項目依賴 項目基於的是2.0.0.RELEASE版本,所以snakeyaml需要單獨引入,高版本已包含 ...
  • 一、多態 多態指的是一類事物有多種形態,一個類有很多個子類,因而多態的概念是基於繼承的 序列數據類型有多種形態:字元串,列表,元組 動物有多種形態:人,狗,豬 1.動物的多種形態 # 動物有多種形態:人類、豬、狗 class Animal: def run(self): # 子類約定俗稱的必須實現這 ...
  • 企業發放的獎金根據利潤提成。 利潤(I)低於或等於10萬元時,獎金可提10%; 利潤高於10萬元,低於20萬元時,低於10萬元的部分按10%提成,高於10萬元的部分,可提成7.5%; 20萬到40萬之間時,高於20萬元的部分,可提成5%; 40萬到60萬之間時高於40萬元的部分,可提成3%; 60萬 ...
  • JZ75 字元流中第一個不重覆的字元 題目 請實現一個函數用來找出字元流中第一個只出現一次的字元。例如,當從字元流中只讀出前兩個字元 "go" 時,第一個只出現一次的字元是 "g"。 當從該字元流中讀出前六個字元 “google" 時,第一個只出現一次的字元是"l"。 方法1 使用LinkedHas ...
  • 訓練模型過程中,經常需要追蹤一些性能指標的變化情況,以便瞭解模型的實時動態,例如:回歸任務中的MSE、分類任務中的Accuracy、生成對抗網路中的圖片、網路模型結構可視化…… 除了追蹤外,我們還希望能夠將這些指標以動態圖表的形式可視化顯示出來。 TensorFlow的附加工具Tensorboar... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...