c++ 表達式和各種轉換運算符介紹

表達式

1. 基礎

c++ 定義了一元和二元運算符

  • 一元:&, *:取地址和解引用
  • 二元: ==, * 相等和乘法
  • 三元:作用與三個對象的

1.1 組合運算符和運算對象

  • 優先級

  • 結合律

  • 運算對象轉換

  • 重載運算符

    • IO庫的>>和<<運算符和類對象的運算
  • 左右值

    • 左值賦值,用作對象的身份
    • 右運算,用對象的值
    • 有時候左值也做運算
      • 取地址符返回指向該對象的指針這個指針是右值
      • 內置解引用,下標的求值結果都是左值

    例如

    decltype 左右值有所不同,如果是左值得到引用類型

    int *p = &a;
    decltype(*p) <-是一個int& 型,因爲解引用是左值
    decltype(&p) <-是一個 int**類型,也就是指向指針的指針
    

1.2 優先級與結合律

普通模式下的運算符就不說了

在優先級相同的情況下,但是沒說按照什麼順序求值。大多情況都不明確

括號無視優先級與結合律

  • 同優先級的沒定義順序的運算來說,是無法判斷的

    cout << i << " " << ++i <<endl;
    我們是不知道i是否先加1的。所以程序是錯誤的
    
    • 規定順序的有

      • && 先求左側運算值
      • ||?:,,都是有順序的
    • 求值順序、優先級、結合律

      如:f()+g()*h()+j()

      • 優先級決定,g()的返回值和h()的返回值相乘
      • 結合律決定,f()的返回值先與g()h()的乘積相加,所得結果與j()的返回值相加
      • 對於函數的調用順序是沒規定的
    • 所以在做這類運算時,函數之間必須要沒有關係

[外鏈圖片轉存中…(img-sAiFlpgO-1583040490611)]

bool不是0就是1

  • 浮點型不能取餘
    • 取餘的定義: m%n如果不等於0,則它的符號和m相同
    • m%(-n)等於m%n, (-m)%n 等於-(m%n)。

1.3 邏輯運算符

關係運算符作用於算術或指針類型,邏輯-》任意轉bool

[外鏈圖片轉存中…(img-EXsUvL2Z-1583040490616)]

  • 短路求值
    • ||:對於左運算對象爲假才進行右運算
    • &&:對於左運算對象爲真才進行右運算

1.4 關係運算符

左結合律

if (i < j < k) //像這種 它屬於 先執行 i<j 得到 一個布爾值 再用這個布爾值跟k比較,也就是如果k>1就一定是真所以儘量不要這樣用

1.5 賦值運算符

左運算對象必須是一個可修改的左值, 初始化不是賦值

  • c++11 允許用{} 括起來賦值
int k;
k = {3.14}; //錯誤: 窄化轉換 如果初始化對象是內置類型,初始化列表,嚴格不能損失精度,所以會報錯
vector<int> v;
vi = {0, 1, 2, 3, 4, 5}; //現在v 有6個元素了
  • 右結合律

    • i = j = 0;
  • 未定義左右運算順序

1.6 自加自減

  • 解引用

    cout << *pd++ << endl; //先輸出當前值在後移一位
    cout << *++pd << endl; //先移一位在後輸出當前值
    
    

1.7 成員訪問運算符

點和箭頭運算符,可訪問成員;

string s1 = "a string ", *p = &s1;
auto n = s1.size();
n = (*p).size();
n = p->size(); //三者意義相同
  • 解引用優先級低於引用

1.8 條件運算符

?:允許我們把if-else 簡短嵌入

  • 都是左值運算
fi = (gr > 90) ? "sss"
    			: (gr < 60) ? "fail" : "pass";
  • 嵌入時要寫括號優先級很低

1.9 位運算

把對象當二進制進行運算

  • 左結合律
功能
~ 取反
>>
<<
左右移
& 位與
^ 位異或
| 位或
  • 若運算小整數將提升位較大的整數一般只轉int
  • 若對象爲負值,那如何處理符號位依賴與機器,是未定義的行爲
  • 移動超屆的會自動捨棄
unsigned char bit = 0233; 
bit << 8 //會自動轉int

  • 位取反

    • 1和0交換

    • 前面的位數都會補0

    • 負數的反碼爲:除符號位外,原碼各位取反,反碼加1,得負數的反碼.

      補碼爲反碼+1,計算機中正數是用原碼顯示,負數用補碼錶示

      char bit = 1; 0~31 1
      ~bit == -2 
      

      根據機器所得 : 得到的1~31 0 ,因符號位爲1所以是補碼,原碼就爲1 0~29 10

1.9.1 位與、位或、位異或運算符

都是兩個對象上的邏輯操作

  • 現在的計算機都是32位的所以int可以移動32位

  • 如果要超過就可以在前面轉型

    1ULL << 34; //unsigned long long
    q &= ~(1<<27); //讓27位爲0
    

1.10 移位運算符

  • 滿足左結合律

1.11 sizeof運算符

返回一條表達式或一個類型名字所佔的字節數

  • 右結合, size_t 類型
sizeof(type);
sizeof expr; //返回表達式結果類型的大小,不計算運算的值
sa_dat data, *p;
sizeof(sa_dat); //這個類型的空間大小
sizeof data; //同上
sizeof p; //指針的大小
sizeof *p; //指針所指空間的大小
  • 對數組會得到數組得總大小
  • 對string 和vector 只會返回類型固定大小不會計算總大小
  • sizeof返回的是常量表達式,所以可以用作數組維度

1.12 逗號運算符

從左向右的求值順序

先求左側的表達式求值,然後將值丟棄,,真正的結果只有右側的表達式

2. 類型轉換

面對浮點轉整型會損失精度

  • 比int小的整數會轉int
  • 在條件中非布爾會轉布爾
  • 初始化右側轉左側
  • 等等

2.1 算術轉換

一個算術類型轉另一個算術類型

  • 有浮點時整數會轉浮點
  • char中(wchar16_t, wchar32_t) 會提升到int,unsigned int。。。。選擇最小的,能容納原來所有可能值的
short + char ; //都轉int
  • 有無符號的結果依賴機器,根據所佔空間大小進行升級和轉換

2.2 隱式轉換

  • 數組用decltype 關鍵字,或取地址,sizeof 及typeid 等時不會發生轉換
  • 指針只有 0, nullptr 可以和 非常量的void*const void*
  • 繼承類之間的指針轉換

2.3 顯示轉換

強制轉換

  • 一個命名的強制轉換形式

    • 一旦類型不符合,會產生未定義的後果
    cast-name<type>(expression);
    type目標類型,expression 要轉換的值
        cast: static_cast, dynamic_cast, const_cast, reinterpret_cast 中的一種
            
    double sl = static_cast<double>(j)/i;
        int a[10] = {0, 1, 2, 3, 4};
        void* S = &a; //非常量對象存入void*
        int *dp = static_cast<int*>(S); //將void*轉換回到初始的指針類型
    
  • const_cast

    • 去掉const性質
    const char *pc;
    const char s[] = "123";
    const char *cp = s;
    char *p = const_cast<char*>(pc);//但p是未定義的行爲去掉const操作
    char *p1 static_cast<char*>(cp); //錯誤static_cast 不能改const性質
    static_cast<string>(cp); //正確,把字面值轉換了,並不會更改掉cp
    const_cast<string>(cp); //錯誤,const_cast只改變常量屬性
    char *p1 const_cast<char*>(cp); //正確 可以通過p1改const性質
    p1可以修改常量cp的值,但cp自己不行    
    
  • reinterpret_cast:

    爲運算對象的位模式提供較低層次上的重新解釋

    int *ip;
    char *pc = reinterpret_cast<char*>(ip);
    與舊式的 char *pc = (char*) ip; 一樣
    

運算符優先級優先級


參考文獻:c++ prime 第五版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章