第二章C++:變數和基本類型

來源:互聯網
上載者:User

介紹語言的基本知識和標準庫

第二章 變數和基本類型

一些語言,如Smalltalk和Python等,在程式運行時檢查資料類型;與之相反,C++是一種待用資料類型語言,它的類型檢查發生在編譯時間。
- 內建類型(built-in type):由語言定義的類型,如int。
- 類類型(class type):程式員自訂的資料類型。

++資料類型告訴我嘛資料的意義以及我們能在資料上執行的操作。++

基本內建類型

術語chunk(塊):用於處理儲存,使儲存具有結構的最基本方法。塊的位元一般是2的冪,這樣可以一次處理8、16、32、64或者128位。注意區分block。

++可定址的最小記憶體塊稱為“位元組(byte)”;儲存的基本單元稱為“字(word)”,通常由幾個位元組組成。++
- 算數類型(arithmetic type):整數、浮點數、單個字元、布爾值
- 整型(integral type):表示整數、字元和布爾值的算術類型合稱為整型
- 字元型:char(單個機器位元組:byte)和wchar_t(寬字元型,用於擴充字元集,比如漢字和日語)
- short:半個機器字長;int:一個機器字長;long:兩個機器字長。ps:在32位機器中int和long的字長通常是相等的。最小儲存空間分別為16位、16位和32位
- 整型的賦值:賦值時,取該值對該類型取值數目求模後的值。
- 浮點型:單精確度、雙精確度、擴充精度(long double)
- 一般而言,float佔1個字(32位元),double佔2個字(64位元),long double以3或4個字(96或128位元)來表示。
- 通常選用double,float的精度損失大(double能至少保證10位有效數字,float只能保證6位),而double的計算代價相對於float可以忽略。
- 16位signed最大數32767,unsigned最大數65535。
- 空類型(void):通常用作無傳回值函數的傳回型別

類型轉換

unsigned char c = -1;     //假設char佔8位元,c的值為255signed char c2 = 256;     //假設char佔8位元,c2的值是未定義的
  • 當我們賦給無符號類型一個超出它表示範圍的值時,結果是初始值對無符號類型表示數值總數模數後的餘數。

  • 當我們賦給帶符號類型一個超出它表示範圍的值時,結果是未定義的(undefined)。此時,程式可能繼續工作、可能崩潰,也可能產生垃圾資料。

  • 不可混用帶符號類型和無符號類型。如果運算式裡這兩種類型都有,帶符號數會自動轉換為無符號數。

字面值常量(literal constant)

  • 稱之為字面值是因為只能用它的值稱呼他,稱之為常量是因為它的值不能夠修改。

  • 只有內建類型存在字面值,沒有類類型的字面值,因此也沒有標準庫類型的字面值。

  • 使用十進位、八進位(0開頭)或十六進位(0x或0X開頭)

//20的三種表示:20      /*十進位*/024     /*八進位*/0x14    /*十六進位*/
  1. 整型字面值:字面值常量類型預設為int或long型。通過加尾碼能夠強制將字面值轉化為long、unsinged、unsigned long,尾碼為L、U、UL或LU(小寫亦可。不提倡使用l,易與1混淆)。

  2. 浮點字面值:十進位或科學計數法來表示(用e或者E)。預設double類型,加F或f表示單精確度,加L或l表示擴充精度。

  3. 布爾字面值:true和false。

  4. 字元字面值

    名稱 書寫
    分行符號 \n
    水平定位字元 \t
    縱向定位字元 \v
    退格符 \b
    斷行符號符 \r
    疑問號 \?
    雙引號 \”
    • \ooo:這裡的ooo表示三個八位元字,這三個數字表示字元的數字值。如’\0’通常表示“Null 字元(null character)”。

    • 也可以用十六進位逸出字元來定義:\xddd。一個反斜線、一個x和一個或多個十六進位數組成。

    • 通用逸出字元:

    • 可列印字元通常用一對單引號定義,如‘a’;在前面加L就能得到wchar_t類型的寬字元字面值,如L‘a’。

    • 不可列印字元和特殊字元都用逸出字元書寫,逸出字元以反斜線開始。

  5. 字串字面值

    • 雙引號括起來的0個或多個字元。

    • 為了相容C語言,C++所有的字串字面值都由編譯器自動在末尾添加一個Null 字元(‘\0’),因此,其實際長度要比它的內容多1。

    • 寬字元字面值:在字串前面加L,如L“asdff”。

    • 多行字面值:兩個字串字面值位置緊鄰且僅由空格、縮排和分行符號分割,則它們實際上是一個整體。

    • 不依賴未定義行為和機器相關行為,否則這樣的程式時不可移植的(nonportable)。

  6. 指標字面值:nullptr

變數

變數提供了程式可操作的有名字的儲存區
- 左值右值
- 左值(lvalue):變數的地址,或者是一個代表“ 對象在記憶體中的位置”的運算式。
- 右值(rvalue):變數的值

變數名出現在賦值運算子的左邊,就是一個左值;而出現在賦值運算子右邊的變數名或字面常量就是一個右值。    如:    val1=val2/8    這裡的val1是個左值,而val2和8都是右值。

- 對象:記憶體中具有類型的地區
- 變數名:即變數的標識符(identifier)。
1. 由字母、數字和底線組成.
2. 變數名必須以字母或底線開頭,並且區分大小寫。(函數體外的變數名不能以底線開頭)
3. C++關鍵字不能用做標識符
4. 不能包含兩個連續的底線
5. 不能以底線開頭後緊跟一個大寫字母

  • 定義對象(如:int a;)

    每個定義都是以類型說明符(type specifier)開始的(如:int)

    int ival(1024);//direct-initialization,直接初始化int ival = 1024;//copy-initialization,複製初始化//註:直接初始化文法更靈活,且效率更高。
    • 列表初始化(list initialization)(C++11新特性)

      int ival{1024};int ival = {1024};long double ld = 3.1415926536;int a{ld}, b = {ld};    //錯誤:轉換未執行,因為存在丟失資訊的風險int c(ld), d = ld;      //正確:轉換執行,且丟失部分值
    • 初始化&賦值:初始化不是賦值。

    • 預設初始化(default initialized):如果內建類型的變數未被顯示初始化,它的值由定義的位置決定。定義於任何函數體之外的變數被初始化為0,內部的將不被初始化。

    • 建議初始化每個內建型變數,以保證程式安全。

    • 初始化

  • 變數的聲明

    extern int i;   //聲明i而非定義iint j;          //定義j
    • 變數只能被定義一次,但能被多次聲明。

    • 如果要在多個檔案中使用同一個變數,就必須將聲明和定義分離。變數的定義必須出現且只能處在在一個檔案中,而其他用到該變數的檔案必須對其進行聲明,卻決不能重複定義。

    • 如果想聲明一個變數而非定義它,在變數名前加關鍵字extern,且不要顯示地初始設定變數:

  • 變數名的範圍(scope):以花括弧分隔

    全域範圍(global scope)

    塊範圍(block scope)

複合類型(compound type)

  • 引用(reference),此處指左值引用(lvalue reference)。

    int ival = 1024;int &refVal = ival; //refVal指向ival(是ival的另一個名字)int &refVal;       //報錯,引用必須被初始化
    • 引用不是對象,只是已經存在的對象的另一個名字。程式將引用和他的初始值綁定(bind)在一起,而不是直接將初始值拷貝給引用。

  • 指標(pointer)

    int i = 42;     int &r = i;     //&緊隨類名出現,因此是聲明的一部分,r是一個引用int *p;         //*緊隨類名出現,因此是聲明的一部分,p是一個指標p = &i;         //&出現在運算式中,是一個取地址符*p = i;         //*出現在運算式中,是一個解引用符int &r2 = *p;
    • 指標是對象,允許賦值和拷貝,且在指標的生命週期內它可以先後指向不同的幾個對象。

    • 指標無需在定義時賦值。

    • 指標類型和它所指向的對象的類型必須匹配。

      int *ip1, *ip2;int val = 4;int *p = &val;
    • 如果指標指向了一個對象,則允許用解引用符(操作符*)來訪問該對象:

      int ival - 42;int *p = &ival;cout << *p;     //由符號*得到指標p所指的對象,輸出42*p = 0;         //由符號*得到指標p所指的對象,即可經由p為變數ival賦值cout << *p;     //輸出0
    • 符號的含義由上下文決定

  • null 指標

int *p1 = nullptr;int *p2 = 0;int *p3 = NULL;     //需要首先#include cstdlib
  • 建議初始化所有指標

  • 面對一條比較複雜的指標或引用的聲明語句時,從右向左閱讀有助於弄清它的真實含義。

const限定符

定義常量。
- 指標和const
- 頂層const(top-level const):表示指標本身是個常量
- 底層const(low-level condt):表示指標所指的對象是個常量

  • 指向常量的指標(pointer to const)

    const double pi = 3.14;double *ptr = &pi;          //錯誤!const double *cptr = &pi;   //正確*cptr = 42;                 //錯誤!cptr指向常量,不能向常量賦值double dval = 3.14;cptr = &dval;               //正確,但不能通過cptr改變dval的值,因為cptr以為自己指向的是常量
  • 常量指標(const pointer)

    int errNum = 0;int *const curErr = &errBum;    //curErr將一直指向errNumconst double pi = 3.14;const double *const pip = &pi;  //pip是一個指向常量對象的常量指標
  • constexpr和常量運算式

    • C++11新標準:將變數聲明為constexpr類型以便由編譯器來驗證變數的值是否是一個常量運算式。(用const,有些常量的具體值直到運行時才能擷取)

    • 在constexpr聲明中如果定義了一個指標,限定符僅對指標有效,與指標所知的對象無關。也就是說它把所定義的對象置為頂層const。

      const int *p = nullptr;     //p是一個指向常量的普通指標constexpr int *q= nullptr;  //q是一個常量指標constexpr int i = 42;constexpr const *p = &i;

處理類型

  • 類型別名(type alias)

    • typedef

      typedef double wages; //wages是double的同義字
      typedef wages base, *p; //base是double的同義字,p是double*的同義字

    • 別名聲明(alias declaration)

      using S1 = Sales_item; //S1是Sales_item的同義字

  • auto類型說明符

    • 讓編譯器替代我們去分析運算式所屬的類型。

    • auto一般會忽略頂層const

      const int i =1; //i是整型常量
      auto b = i; //b是一個整數
      const auto c = i; //c是整型常量

  • decltype類型指示符

    const int ci = 0, &cj = ci; decltype(ci) x = 0;         //x的類型是const intdecltype(cj) y = x;         //y的類型是const int&,y綁定到變數xdecltype(cj) z;             //錯誤:z是一個引用,必須初始化
    int i = 42, *p = &i, &r = i;decltype(r + 0) b;  //正確:加法的結果是int,因此b是一個未初始化的intdecltype(*p) c;     //錯誤:c是int&,必須初始化
    • decltype((v))(注意雙層括弧)的結果永遠是引用。

    • decltype處理頂層const和引用的方式與auto有些許不同。如果decltype使用的運算式是一個變數,則decltype返回該變數的類型(包括頂層const和引用在內)。

自訂資料結構

  • 標頭檔通常包含哪些只能被定義一次的實體,如類、const和constexpr變數等。

  • 前置處理器(preprocessor):如#include,當前置處理器看到#include標記時就會用指定的標頭檔內容替代#include。

  • 標頭檔保護符(header guard):有效防止重複包含發生

    • 一般把預先處理變數的名字全部大寫

      #ifdef //若且唯若變數已定義時為真
      #ifndef //若且唯若變數未定義是為真
      #define //把一個名字設定為預先處理變數
      #endif //與#ifdef和#ifndef匹配,執行它們的後續操作知道#endif指令止

#ifndef SALES_DATA_H#define SALES_DATA_H#include <string>struct Sales_data {    ... //此處省略};#endif

參考:C++Primer第五版

介紹語言的基本知識和標準庫

相關文章:

第一章C++:函數傳回值、GNU編譯器命令

第三章C++:字串string、向量vector和數組

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.