從C++ int類型的變量范圍談起


從學習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類型字符,其實現的動機難以理解,不過從某程度上說明標准與實現之間的距離,對於一個函數的實現,尤其是不常用的功能,最好還是自己進行確認。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM