標籤:網站 學習 有符號 建構函式 最小 理解 操作 dig gcc
從學習C語言開始,int類型所佔位元組數,以及數值範圍就是一個揮之不去的問題。一開始會死記硬背一個char 1個位元組,一個位元組8個bit。64位機器上面一個int 4個位元組,32位機器上面不一樣。那時候並不知道編譯器也分很多種,每一種實現的細節不一樣,也不知道各家編譯器是遵循C++標準委員會的標準。後來學會像編譯器求證,以其輸出為準,也學會向標準求證。
在一篇部落格上面看到用numeric_limits 類可以方便地瞭解各個類型的取值範圍以及佔用記憶體,於是滿心歡喜地將代碼運行,發現有些問題:
#include<iostream>#include <limits>using namespace std;int main(){ cout << "type: \t\t" << "------------------size-----------------------"<< endl; cout << "bool: \t\t" << "Bytes:" << sizeof(bool); cout << "\tMaxValue:" << (numeric_limits<bool>::max)(); cout << "\t\tMinValue:" << (numeric_limits<bool>::min)() << endl; cout << "char: \t\t" << "Bytes:" << sizeof(char); cout << "\tMaxValue:" << (numeric_limits<char>::max)(); cout << "\t\tMinValue:" << (numeric_limits<char>::min)() << endl; cout << "signed char: \t" << "Bytes:" << sizeof(signed char); cout << "\tMaxValue:" << (numeric_limits<signed char>::max)(); cout << "\t\tMinValue:" << (numeric_limits<signed char>::min)() << endl; cout << "unsigned char: \t" << "Bytes:" << sizeof(unsigned char); cout << "\tMaxValue:" << (numeric_limits<unsigned char>::max)(); cout << "\t\tMinValue:" << (numeric_limits<unsigned char>::min)() << endl; cout << "wchar_t: \t" << "Bytes:" << sizeof(wchar_t); cout << "\tMaxValue:" << (numeric_limits<wchar_t>::max)(); cout << "\t\tMinValue:" << (numeric_limits<wchar_t>::min)() << endl; cout << "short: \t\t" << "Bytes:" << sizeof(short); cout << "\tMaxValue:" << (numeric_limits<short>::max)(); cout << "\t\tMinValue:" << (numeric_limits<short>::min)() << endl; cout << "int: \t\t" << "Bytes:" << sizeof(int); cout << "\tMaxValue:" << (numeric_limits<int>::max)(); cout << "\tMinValue:" << (numeric_limits<int>::min)() << endl; cout << "unsigned: \t" << "Bytes:" << sizeof(unsigned); cout << "\tMaxValue:" << (numeric_limits<unsigned>::max)(); cout << "\tMinValue:" << (numeric_limits<unsigned>::min)() << endl; cout << "long: \t\t" << "Bytes:" << sizeof(long); cout << "\tMaxValue:" << (numeric_limits<long>::max)(); cout << "\tMinValue:" << (numeric_limits<long>::min)() << endl; cout << "type: \t\t" << "************size**************"<< endl; return 0;}
運行結果:
常用的int,long等類型的取值範圍確實如願顯示。但是,在關於 char的判斷中,有顯示的問題。從使用的角度而言,其實char用於表示字元,判斷大小並不合理。當然,這隻是一個“完形填空”式的推導。既然顯示在螢幕上的輸出有問題,本著鑽研精神,要弄清楚為什麼。
首先是假設:
1. cout無法處理這個numeric_limit<char>::max()函數
2.numeric_limit<char>::max()的傳回值並不是可顯示字元。
為了驗證第一點,我找到C++標準委員會的網站,找到C++14的草稿標準:
從這裡看出,返回的是模板類型 T的建構函式。似乎排除了第一種可能。但標準太不具體,我在Clion上面用debug模式直接找到庫檔案來確認。值得一提的是編譯器版本:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2)。
第一步:
再往下一層:
在limits的實現裡面,都是再用宏定義的位操作來實現最大和最小值的擷取。先看__glibcxx_digits宏定義。這裡面的邏輯很簡單,佔用位元組數乘以__CHAR_BIT__減去符號位(1位)。在char的例子裡面,得出來的位元是7。從這裡不妨猜測,編譯器對一個位元組大小的定義很有可能是基於__CHAR_BIT__的。在一篇博文看過對於古老的機器,char類型只有7bit。按照這個猜測,在描述內建int型大小的時候,就可以說一個int等於4個char。這個猜測挺有意思,不過有待考究。
進一步分析,__glicxx_min宏定義,對於傳入的類型_Tp,如果有符號,就執行(_Tp)1 << _glibcxx_digits(_Tp), 沒有就是(_Tp)0.
對於char型,它居然被是認為有符號的! 所以最小值的計算變成 (char)1 << 7,二進位表示10000000, -128.
一個被賦值為-128的char類型字元,恐怕並不是可顯示字元。這裡面的實現動機也很難理解。
花費了一個下午最終知道了一下計算的細節但是沒有很瞭解動機,有些鬱悶。改天會再解一下cout的運行,看其中再有無關聯。
也希望有高人看到能夠解答。
關於C++ numeric_limits<char>