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

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

1.1 整數(shù)類型long long

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

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

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

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

long long x = 65536LL;

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

long long x = 65536;

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

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

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

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

作為一個(gè)新的整型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)中對(duì)標(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也加入了對(duì)其格式化打印的能力。新增的長度指示符ll可以用來指明變量是一個(gè)long long類型,所以我們分別使用%lld%llu來格式化有符號(hào)和無符號(hào)的long long整型了。當(dāng)然,使用C++標(biāo)準(zhǔn)的流輸入/輸出是一個(gè)更好的選擇。

主站蜘蛛池模板: 信丰县| 廉江市| 禄丰县| 广水市| 观塘区| 和田县| 兰坪| 开鲁县| 怀柔区| 陈巴尔虎旗| 广南县| 南江县| 富阳市| 苗栗县| 天水市| 晋州市| 那曲县| 湘阴县| 博兴县| 永康市| 伊通| 忻城县| 闽侯县| 彝良县| 龙泉市| 大荔县| 舒城县| 济南市| 高邑县| 湄潭县| 清流县| 台北市| 辽阳市| 西畴县| 财经| 虹口区| 枣阳市| 察雅县| 赞皇县| 大石桥市| 文成县|