C Primer 第2章 變量和基本類型1 基本內置類型算數類型類型轉換字面值常量2 變量變量定義3 復合類型引用d左引用指針d4 const限定符指針和constconstexpr和常量表達式5 處理類型類型別名auto類型說明符decltype類型指示符6 自定義數據結構
bool的最小尺寸未定義 char16_t和char32_t的最小 尺寸分別為16位和32位,含義是Unicode字符,short和int都是16位(-32768~32768),long是32位(-21E~21E),long long是64位。 float是6位有效數字,double是10位有效數字,long double是10位有效數字。
以下是選擇類型的一些經驗準則:
當明確知曉數值不可能位負時,選用無符號類型。使用int執行整數運算。在實際應用中,short常常顯得太小而long一般和int有一樣的尺寸。如果數值超過int的表示范圍,選用long long。
在算術表達式中不要使用char或bool,因為類型char在一些機器上是有符號的,一些是沒符號的。如果需要使用一個不大的整數,那么明確指定是signed char(-128~127)或者unsigned char(0~255)
執行浮點數運算選用double,這是因為float通常精度不夠,而且double和float的計算代價相差無幾。對于某些機器來說,甚至double比float更快。long double在一般情況下是沒有必要的,況且它帶來運行時的消耗也不容忽視。十進制字面值的類型是int、long和long long中尺寸最小的那個。 八進制和十六進制字面值的類型是int、unsigned int、long、unsigned long、long long和unsigned long long中的尺寸最小者。 如果一個字面值連與之關聯的最大的數據類型都放不下,將產生錯誤。類型short沒有對應的字面值。 盡管整型字面值可以存儲在帶符號數據類型中,但嚴格來說,十進制字面值不會是負數,負號并不在字面值之內,它的作用僅僅是對字面值取負數而已。
由單引號括起來的一個字符稱為char型字面值,雙引號括起來的零個或多個字符則構成字符串型字面值,編譯器會在每個字符串的結尾處添加一個空字符’/0’,因此,字符串字面值的實際長度比內容多1。
泛化的轉義序列:/x后緊跟1個或多個十六進制數字,或者/后緊跟1個、2個或3個八進制數字,其中數字部分表示的是字符對應的數值。 注意:如果反斜線/后面跟著的八進制數字超過3個,只有前三個數字與/構成轉義序列。相反,/x要用到后面跟著的所有數字。
WARNING:初始化不是賦值,初始化的含義是創建變量時賦予其一個初始值,而賦值的含義是把對象的當前值擦除,而以一個新值來替代。 C++11:可用{ }來初始化變量 如果想聲明一個變量而非定義它,就在變量名前添加關鍵字extern,而且不要顯示的初始化變量。任何包含了顯示初始化的聲明即稱為定義。會抵消extern的作用。
extern int i; //聲明i而非定義iint j; //聲明并定義j變量能且只能被定義一次,但是可以被申請多次。
引用并非對象,它只是為一個已經存在的對象所起的另外一個名字。引用只能綁定在對象上,而不能與字面值或某個表達式的計算結果綁定在一起。
因為引用不是對象,沒有實際地址,所以不能定義指向引用的指針。 如果指針指向了一個對象,則允許使用解引用符*來訪問對象。 C++11:得到空指針最直接的辦法就是用字面值nullptr來初始化指針,它可以被轉換成任意其他的指針類型。 void* 指針是一種特殊的指針類型,可用于存放任意對象的地址。不能直接操作void*指針所指的對象,因為我們并不知道這個對象到底是什么類型,也就無法確定能在這個對象上做哪些操作。
如果想在多個文件之間共享const對象,必須在變量的定義之前添加extern關鍵字。 常量引用是對const的引用,引用的對象是常量還是非常量可以決定其能所參與的操作,卻無論如何都不會影響到引用和對象的綁定關系本身。 常量引用僅對引用可參與的操作做出了限定,對于引用的對象本身是不是一個常量未作限定。因為對象也可能是個非常量,所以允許通過其他途徑改變它的值:
int i = 42;int &r1 = i; //引用ri綁定對象iconst int &r2 = i; //r2也綁定對象i,但是不允許通過r2修改i的值r1 = 0; //r1并非常量,i的值修改為0r2 = 0; //錯誤:r2是一個常量引用指向常量的指針不能用于改變其所指對象的值,要想存放常量對象的地址,只能使用指向常量的指針:
const double pi = 3.14;const double *cptr = π兩個例外: - 允許令一個指向常量的指針指向一個非常量對象:
double dval = 3.14;cptr = &dval; //正確:但是不能通過cptr改變dval的值所謂指向常量的指針僅僅要求不能通過該指針改變對象的值,而沒有規定那個對象的值不能通過其他途徑改變。 指針本身是一個常量并不意味著不能通過指針修改其所指對象的值,能否這樣做完全依賴于所指對象的類型。 把*放在const關鍵字之前用以說明指針是一個常量,即不變的是指針本身的值而非指向的那個值。 想讓指針指向常量,就必須在前面加const,想讓指針是常量,就得把*放到const前面
常量表達式是指不會改變并且在編譯過程就能得到計算結果的表達式。 C++11允許將變量聲明位constexpr類型以便由編譯器來驗證變量的值是否是一個常量表達式。
一般來說,如果你認定變量是一個常量表達式,那么就吧它聲明成constexpr類型。
自定義類、IO庫、string類型都不是字面值類型,不能被定義成constexpr,一個constexpr指針的初始值必須是nullptr或者0,或者是存儲于某個固定地址中的對象。
*在constexpr聲明中如果定義了一個指針,限定符constexpr僅對指針有效,與指針所指的對象無關:
const int *p = nullptr; //p是一個指向整型常量的指針constexpr int *q = nullptr; //q是一個指向整數的常量指針它能讓編譯器去分析表達式的類型從而確定變量的類型,一條聲明語句只能由一個基本數據類型。 auto一般會忽略掉頂層const,同時底層const則會保留下來。
它的作用是選擇 并返回操作數的數據類型,不實際計算表達式的值: decltype (f()) sum = x;
編譯器并不實際調用函數f,而是使用當調用發生時f的返回值類型作為sum的類型。
如果給變量加上了一層或多層括號,編譯器就會把它當成是一個表達式。變量是一種可以作為賦值語句左值的特殊表達式,賦值是會產生引用的一類典型表達式,引用的類型就是左值的類型,所以這樣的decltype就會得到引用類型,而非變量的類型。
預處理命令:在編譯前執行的一段程序,可以部分地改變我們所寫的程序。 頭文件保護符 #ifdef
當且僅當變量已定義時為真 #ifndef
當且僅當變量未定義時位真 一旦檢測結果位真,則執行后續操作直至遇到#endif
為止。
新聞熱點
疑難解答
圖片精選