官术网_书友最值得收藏!

第1章 新基礎(chǔ)類型(C++11~C++20)

1.1 整數(shù)類型long long

整型long long雖然是C++11才新加入標(biāo)準(zhǔn)的,但是我們似乎很早就開始使用這個類型了,這其中包含了一個有趣的故事。

long long這個類型早在1995年6月之前就由羅蘭·哈丁格(Roland Hartinger)提出申請加入C++標(biāo)準(zhǔn)。但是當(dāng)時的C++標(biāo)準(zhǔn)委員會以C語言中不存在這個基本類型為由,拒絕將這個類型加入C++中。而就在C++98標(biāo)準(zhǔn)出臺的一年后,C99標(biāo)準(zhǔn)就添加了long long這個類型,并且流行的編譯器也紛紛支持了該類型,這也就是我們很早就接觸到long long的原因。在此之后C++標(biāo)準(zhǔn)委員會在C++11中才有計劃將整型long long加入標(biāo)準(zhǔn)中。

我們知道long通常表示一個32位整型,而long long則是用來表示一個64位的整型。不得不說,這種命名方式簡單粗暴。不僅寫法冗余,而且表達(dá)的含義也并不清晰。如果按照這個命名規(guī)則,那么128位整型就該被命名為long long long了。但是不管怎么樣,long long既然已經(jīng)加入了C++11的標(biāo)準(zhǔn),那么我們能做的就是適應(yīng)它,并且希望不會有long long long這種類型的誕生。

C++標(biāo)準(zhǔn)中定義,long long是一個至少為64位的整數(shù)類型。請注意這里的用詞“至少”,也就說long long的實(shí)際長度可能大于64位。不過我至今也沒有看到大于64位長度的long long出現(xiàn)。另外,long long是一個有符號類型,對應(yīng)的無符號類型為unsigned long long,當(dāng)然讀者可能看到過諸如long long intunsigned long long int等類型,實(shí)際上它們和long longunsigned long long具有相同的含義。C++標(biāo)準(zhǔn)還為其定義LLULL作為這兩種類型的字面量后綴,所以在初始化long long類型變量的時候可以這么寫:

long long x = 65536LL;

當(dāng)然,這里可以忽略LL這個字面量后綴,直接寫成下面的形式也可以達(dá)到同樣的效果:

long long x = 65536;

要強(qiáng)調(diào)的是,字面量后綴并不是沒有意義的,在某些場合下我們必須用到它才能讓代碼的邏輯正確,比如下面的代碼:

long long x1 = 65536 << 16;      // 計算得到的x1值為0
std::cout << "x1 = " << x1 << std::endl;

long long x2 = 65536LL << 16;    // 計算得到的x2值為4294967296(0x100000000)
std::cout << "x2 = " << x2 << std::endl;

以上代碼的目的是將65536左移16位,以獲得一個更大的數(shù)值。但是,x1計算出來的值卻是0,沒有增大反而減小了。原因是在沒有字面量后綴的情況下,這里的65536被當(dāng)作32位整型操作,在左移16位以后,這個32位整型的值變成了0,所以事實(shí)是將0賦值給了x1,于是我們看到x1輸出的結(jié)果為0。而在計算x2的過程中,代碼給65536添加了字面量后綴LL,這使編譯器將其編譯為一個64位整型,左移16位后仍然可以獲得正確的結(jié)果:4294967296(0x100000000)。另外,有些編譯器可能在編譯long long x1 = 65536 << 16;的時候顯示一些警告提示,而另一些編譯器可能沒有,無論如何我們必須在編寫代碼的時候足夠小心,避免上面情況的發(fā)生。

和其他整型一樣,long long也能運(yùn)用于枚舉類型和位域,例如:

 enum longlong_enum : long long {
      x1,
      x2
 };

 struct longlong_struct {
      long long x1 : 8;
      long long x2 : 24;
      long long x3 : 32;
 };

std::cout << sizeof(longlong_enum::x1) << std::endl;  // 輸出大小為8
std::cout << sizeof(longlong_struct) << std::endl;    // 輸出大小為8

作為一個新的整型long long,C++標(biāo)準(zhǔn)必須為它配套地加入整型的大小限制。在頭文件中增加了以下宏,分別代表long long的最大值和最小值以及unsigned long long的最大值:

#define LLONG_MAX 9223372036854775807LL         // long long的最大值
#define LLONG_MIN (-9223372036854775807LL - 1)  // long long的最小值
#define ULLONG_MAX 0xffffffffffffffffULL        // unsigned long long的最大值

在C++中應(yīng)該盡量少使用宏,用模板取而代之是明智的選擇。C++標(biāo)準(zhǔn)中對標(biāo)準(zhǔn)庫頭文件做了擴(kuò)展,特化了long longunsigned long long版本的numeric_ limits類模板。這使我們能夠更便捷地獲取這些類型的最大值和最小值,如下面的代碼示例:

#include <iostream>
#include <limits>
#include <cstdio>
int main(int argc, char *argv[])
{
      // 使用宏方法
      std::cout << "LLONG_MAX = " << LLONG_MAX << std::endl;
      std::cout << "LLONG_MIN = " << LLONG_MIN << std::endl;
      std::cout << "ULLONG_MAX = " << ULLONG_MAX << std::endl;

      // 使用類模板方法
      std::cout << "std::numeric_limits<long long>::max() = " 
            << std::numeric_limits<long long>::max() << std::endl;
      std::cout << "std::numeric_limits<long long>::min() = " 
            << std::numeric_limits<long long>::min() << std::endl;
      std::cout << "std::numeric_limits<unsigned long long>::max() = " 
            << std::numeric_limits<unsigned long long>::max() << std::endl;

      // 使用printf打印輸出
      std::printf("LLONG_MAX = %lld\n", LLONG_MAX);
      std::printf("LLONG_MIN = %lld\n", LLONG_MIN);
      std::printf("ULLONG_MAX = %llu\n", ULLONG_MAX);
}

輸出結(jié)果如下:

LLONG_MAX = 9223372036854775807
LLONG_MIN = -9223372036854775808
ULLONG_MAX = 18446744073709551615
std::numeric_limits<long long>::max() = 9223372036854775807
std::numeric_limits<long long>::min() = -9223372036854775808
std::numeric_limits<unsigned long long>::max() = 18446744073709551615
LLONG_MAX = 9223372036854775807
LLONG_MIN = -9223372036854775808
ULLONG_MAX = 18446744073709551615

以上代碼很容易理解,唯一需要說明的一點(diǎn)是,隨著整型long long的加入,std::printf也加入了對其格式化打印的能力。新增的長度指示符ll可以用來指明變量是一個long long類型,所以我們分別使用%lld%llu來格式化有符號和無符號的long long整型了。當(dāng)然,使用C++標(biāo)準(zhǔn)的流輸入/輸出是一個更好的選擇。

主站蜘蛛池模板: 岳西县| 大名县| 弋阳县| 汤原县| 慈利县| 南雄市| 靖安县| 通辽市| 南陵县| 孙吴县| 毕节市| 凌源市| 黄石市| 石嘴山市| 金沙县| 安宁市| 铁岭市| 杭州市| 都匀市| 汉源县| 阳高县| 隆昌县| 台东县| 苍南县| 福安市| 新巴尔虎右旗| 东城区| 衡水市| 罗平县| 裕民县| 竹山县| 理塘县| 乌恰县| 青海省| 察雅县| 武宁县| 祥云县| 梓潼县| 慈利县| 绥棱县| 宜春市|