1. 程式人生 > >【C++學習筆記】型別轉換和跳轉語句

【C++學習筆記】型別轉換和跳轉語句

一、型別轉換
  在C++語言中,如果兩種型別由關聯,那麼當程式需要其中一種型別的運算物件時,可以用另一種型別的物件或值來替代,即如果如果兩種型別可以相互轉換(conversion),那麼它們就是關聯的。下面的例子中會先根據型別轉換規則設法將運算物件的型別統一後再求值,並且 型別的轉換是自動執行的,因而也被稱為隱式轉換(implicit conversion)。

int ival = 3.14 + 3;             //編譯器可能會警告該運算損失了精度

發生隱式轉換的條件:
  ①大多數表示式中,比int型別小的整型值首先提升為較大的整數型別;
  ②在條件中,非布林值轉換為布林值;
  ③初始化過程中,初始值轉換為比變數的型別;在賦值語句中,右側運算物件轉換成左側運算物件的型別;
  ④如果算術運算或關係運算物件有多種型別,需要轉換成同一種類型;
  ⑤函式呼叫時也會發生型別轉換。

1.1 算術轉換
  算術轉換(arithmetic conversion)的含義是把一種算術型別轉換成另一種算術型別。算術轉換規則定義了一套型別轉換的層次,其中運算子的運算將轉換成最寬的型別,即如果一個運算物件的型別是long double,那麼不論另外一個運算物件的型別是什麼都會轉換為long double。
1.1.1 整數提升(integral promotion)
  負責把小整數型別換成大的整數型別。對於bool、char、sigied char、unsigned char、short和unsigned short等型別來說,只要它們所有可能的值都能存在int裡,它們就會提升為int型別,否則提升為unsigned int型別,即布林值false提升為0,true提升為1。
1.1.2 無符號型別的運算物件
  如果某個運算的運算子的運算物件型別不一致,這些運算物件將轉換成同一種類型。但是如果某個運算物件的型別是無符號型別,那麼轉換的結果就要依賴於機器中各個整數型別的相對大小了。一般地,先執行整數提升,如果結果的型別匹配,無需進行進一步提升,如果運算物件的型別要麼都是帶符號,要麼都是無符號,則小型別運算物件轉成較大的型別。
  如果一個運算物件是無符號型別,另外一個運算物件是帶符號型別,而且其中的無符號型別不小於帶符號型別,那麼帶符號的運算物件轉換成unsigned int型別。如果帶符號型別大於無符號型別,此時轉換的結果依賴於機器,如果無符號型別的所有值都能存在該帶符號型別中,則無符號的運算物件轉換成帶符號型別,否則帶符號型別的運算物件轉換成無符號型別。

1.2 其他隱式型別轉換
  除了算術轉換之外還有幾種隱式型別轉換,如下:
1.2.1 陣列轉換成指標
  在大多數用到陣列的表示式中,陣列自動轉換成指向陣列首元素的指標:

int ia[10];                    //含有10個整數的陣列
int *ip = ia;                  //ia轉換成指向陣列首元素的指標

  當陣列被用作decltype關鍵字的引數,或者作為取地址(&)、sizeof及typeid等運算子的運算物件,以及用一個引用來初始化陣列時,上述轉換不會發生。
1.2.2 指標的轉換
  C++還規定了幾種其他的指標轉換方式,包括常量整數值0或字面值nullptr能轉換成任意指標型別,指向任意非常量的指標能轉換成void*,指向任意物件的指標能轉換成const void*。
1.2.3 轉換成布林型別
  存在一種從算術型別或指標型別向布林型別自動轉換的機制,如果指標或算術型別的值為0,轉換的結果是false。否則轉換結果是true。
1.2.4 轉換成常量
  允許將指向非常量型別的指標轉換成指向相應的常量型別的指標,對於引用也是這樣,即如果T是一種型別 ,我們就能將指向T的指標或引用分別轉換成指向const T的指標或者引用。

int j;
const int &k = j;           //非常量轉換成const int的引用
const int *p = &j;          //非常量的地址轉換成const的地址
int &r = k,*q = p;          //錯誤,不允許const轉換非常量

1.2.5 類型別定義的轉換
  類型別能定義由編譯器自動執行的轉換,不過編譯器每次只能執行一種類型別的轉換。

string s,t = "a value";      //字串字面值轉換成string型別
while(cin >> s)              //while的條件部分把cin轉換成布林值

1.3 顯式轉換
  有時希望顯式地將物件強制轉換成另外一種型別,這種方法稱為強制型別轉換(cast)。
1.3.1 命名的強制型別轉換
  一個命名的強制型別轉換具有如下形式:

cast-name<type>(expression);

  其中type是轉換的目標型別而expression是要轉換的值;如果type是引用型別,則結果是左值,cast_name是static_cast、dynamic_cast、const_castreinterpret_cast中的一種。

二、跳轉語句
  跳轉語句中斷當前的執行過程,C++語言提供了四種跳轉語句:break、continue、goto和return。
①break語句
  break語句負責終止離它最近的while、do while、for或switch語句,並從這些語句之後的第一條語句開始繼續執行。
②continue語句
  continue語句終止最近的迴圈中的當前迭代並立即開始下一次迭代。
③goto語句
  goto語句的作用是從goto語句無條件跳轉到同一函式內的另一條語句。需要注意的是最好不要在程式中使用goto語句,因為它使得程式既難理解又難修改。
  goto語句的語法形式為:

goto label;

  其中label是用於表示一條語句的識別符號。帶標籤語句是一種特殊的語句,在它之前有一個標示符以及一個冒號,標籤標示符獨立於變數或其他標示符的名字,即標籤標示符和程式中其它實體的標示符使用同一名字也不會相互干擾。goto語句和控制權轉向的那條帶標籤的語句必須位於同一函式之內,以及不能將程式的控制權從變數的作用域轉移到作用域之外。

//...
goto end;
int ix = 10;                //錯誤,goto語句繞過了一個帶初始化的變數定義
end:
   //錯誤,此處的程式碼需要使用ix,但是goto語句繞過了它的宣告
   ix = 42;

  向後跳過一個已經執行的定義是合法的,並且意味著系統將銷燬該變數,然後重新建立它。

//向後跳過一個帶初始化的變數定義是合法的
begin:
   int sz = get_size();
   if (sz <= 0){
      goto begin;
   }

參考文獻:
①C++ Primer 第五版。