C++primer 第 4 章 表達式 4.7條件運算符 4.8位運算符 4.9 sizeof運算符 4.10逗號運算符 4.11類型轉換 4 . 1 2 運算符優先級表

4.7條件運算符

  • 條件運算符(?:)允許我們把簡單的if else邏輯嵌入到單個表達式當中,條件運算符按照如下形式使用:
  • cond ? expr1 : expr2;其中cond是判斷條件的表達式,而expr1和expr2是兩個類型相同或可能轉換為某個公共類型的表達式。條件運算符的執行過程是:首先求cond的值,如果條件為真對expr1求值并返回該值,否則對expr2求值并返回該值。舉個例子,我們可以使用條件運算符判斷成績是否合格:
  • string finalgrade = (grade<60) ?"fail" : "pass”;
  • 條件部分判斷成績是否小于60。如果小于,表達式的結果是"fail",否則結果是"pass"。有點類似于邏輯與運算符和邏輯或運算符(&&和||),條件運算符只對expr1和expr2中的一個求值。
  • 當條件運算符的兩個表達式都是左值或者能轉換成同一種左值類型時,運算的結果是左值;否則運算的結果是右值。

嵌套條件運算符

  • 允許在條件運算符的內部嵌套另外一個條件運算符。也就是說,條件表達式可以作為另外一個條件運算符的cond或expr
  • 舉個例子,使用一對嵌套的條件運算符可以將成績分成三檔:優秀(highpass)>合格(pass)和不合格(fail):
  • finalgrade=(grade>90)?"highpassn:(grade<60)?“fail":"pass";
  • 第一個條件檢查成績是否在90分以上,如果是,執行符號?后面的表達式,得到"highpass";如果否,執行符號:后面的分支。這個分支本身又是一個條件表達式,它檢查成績是否在60分以下,如果是,得到"fail";否則得到"pass"。
  • 條件運算符滿足右結合律,意味著運算對象(一般)按照從右向左的順序組合。因此在上面的代碼中,靠右邊的條件運算(比較成績是否小于60)構成了靠左邊的條件運算的:分支。
  • 隨著條件運算嵌套層數的增加,代碼的可讀性急劇下降.因此,條件運算的嵌套最好別超過兩到三層

4.8位運算符

  • 位運算符作用于整數類型的運算對象,并把運算對象看成是二進制位的集合。位運算符提供檢查和設置二進制位的功能,如17.2節(第640頁)將要介紹的,一種名為bitset的標準庫類型也可以表示任意大小的二進制位集合,所以位運算符同樣能用于bitset類型.

  • 一般來說,如果運算對象是''小整型”,則它的值會被自動提升(參見4.11.1節,第142頁)成較大的整數類型。運算對象可以是帶符號的,也可以是無符號的。如果運算對象是帶符號的且它的值為負,那么位運算符如何處理運算對象的“符號位”依賴于機器。而且,此時的左移操作可能會改變符號位的值,因此是一種未定義的行為。
  • 關于符號位如何處理沒有明確的規定,所以強烈建議僅將位運算符用于處理無符號類型。

移位運算符

  • 之前在處理輸入和輸出操作時,我們已經使用過標準IO庫定義的<<運算符和>>運算符的重載版本。這兩種運算符的內置含義是對其運算對象執行基于二進制位的移動操作,首先令左側運算對象的內容按照右側運算對象的要求移動指定位數,然后將經過移動的(可能還進行了提升)左側運算對象的拷貝作為求值結果。其中,右側的運算對象一定不能為負,而且值必須嚴格小于結果的位數,否則就會產生未定義的行為。二進制位或者向左移(?)或者向右移(?),移出邊界之外的位就被舍棄掉了:

  • 左移運算符(<<)在右側插入值為0的二進制位。右移運算符(>>)的行為則依賴于其左側運算對象的類型:如果該運算對象是無符號類型,在左側插入值為0的二進制位:
  • 如果該運算對象是帶符號類型,在左側插入符號位的副本或值為0的二進制位,如何選擇要視具體環境而定。

位求反運算符

  • 位求反運算符( ~) 將運算對象逐位求反后生成一個新值,將 1 置為0、將 0 置為1:
  • char類型的運算對象首先提升成int類型,提升時運算對象原來的位保持不變,往高位(highorderposition)添加0即可。因此在本例中,首先將bits提升成int類型,增加24個高位0,隨后將提升后的值逐位求反。

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

  • 與(&)、或(|)、異或(^)運算符在兩個運算對象上逐位執行相應的邏輯操作:

  • 對于位與運算符(&)來說,如果兩個運算對象的對應位置都是1則運算結果中該位為1,否則為0。對于位或運算符(|)來說,如果兩個運算對象的對應位置至少有一個為1則運算結果中該位為1,否則為0。對于位異或運算符(^)來說,如果兩個運算對象的對應位置有且只有一個為1則運算結果中該位為1,否則為0

移位運算符(又叫10運算符)滿足左結合律

  • 盡管很多程序員從未直接用過位運算符,但是幾乎所有人都用過它們的重載版本來進行10操作。重載運算符的優先級和結合律都與它的內置版本一樣,因此即使程序員用不到移位運算符的內置含義,也仍然有必要理解其優先級和結合律。
  • 因為移位運算符滿足左結合律,所以表達式

4.9 sizeof運算符

  • sizeof運算符返回一條表達式或一個類型名字所占的字節數。sizeof運算符滿足右結合律,其所得的值是一個size_t類型(參見3.5.2節,第 103頁)的常量表達式(參 見2.4.4節,第 58頁)。運算符的運算對象有兩種形式:
  • sizeof (type)
  • sizeof expr

  • 這些例子中最有趣的一個是sizeof *p。首先,因為sizeof滿足右結合律并且與*運算符的優先級一樣,所以表達式按照從右向左的順序組合。也就是說,它等價于sizeof(*p)
  • 其次,因為sizeof不會實際求運算對象的值,所以即使p是一個無效(即未初始化)的指針(參見2.3.2節,第47頁)也不會有什么影響。在sizeof的運算對象中解引用一個無效指針仍然是一種安全的行為,因為指針實際上并沒有被真正使用。
  • sizeof不需要真的解引用指針也能知道它所指對象的類型。新標準允許我們使用作用域運算符來獲取類成員的大小。通常情況下只有通過類的對象才能訪問到類的成員,但是sizeof運算符無須我們提供一個具體的對象,因為要想知道類成員的大小無須真的獲取該成員。
  • sizeof運算符的結果部分地依賴于其作用的類型:
  • 對char或者類型為char的表達式執行sizeof運算,結果得1。
  • 對引用類型執行sizeof運算得到被引用對象所占空間的大小。
  • 對指針執行sizeof運算得到指針本身所占空間的大小。
  • 對解引用指針執行sizeof運算得到指針指向的對象所占空間的大小,指針不需有效。
  • 對數組執行sizeof運算得到整個數組所占空間的大小,等價于對數組中所有的元素各執行一次sizeof運算并將所得結果求和。注意,sizeof運算不會把數組轉換成指針來處理。
  • 對string對象或vector對象執行sizeof運算只返回該類型固定部分的大小,不會計算對象中的元素占用了多少空間。
  • 因為執行sizeof運算能得到整個數組的大小,所以可以用數組的大小除以單個元素的大小得到數組中元素的個數:

?

4.10逗號運算符

  • 逗號運算符含有兩個運算對象,按照從左向右的順序依次求值。和邏輯與、邏輯或以及條件運算符一樣,逗號運算符也規定了運算對象求值的順序。
  • 對于逗號運算符來說,首先對左側的表達式求值,然后將求值結果丟棄掉。逗號運算符真正的結果是右側表達式的值。如果右側運算對象是左值,那么最終的求值結果也是左值。
  • 逗號運算符經常被用在for循環當中:

?

4.11類型轉換

  • 在C++語言中,某些類型之間有關聯。如果兩種類型有關聯,那么當程序需要其中一種類型的運算對象時,可以用另一種關聯類型的對象或值來替代。換句話說,如果兩種類
  • 型可以相互轉換(conversion),那么它們就是關聯的。舉個例子,考慮下面這條表達式,它的目的是將ival初始化為6:
  • int ival = 3.541 + 3; / / 編譯器可能會警告該運算損失了精度
  • 加法的兩個運算對象類型不同:3.541的類型是double,3的類型是int。C++語言不會直接將兩個不同類型的值相加,而是先根據類型轉換規則設法將運算對象的類型統一后再求值。上述的類型轉換是自動執行的,無須程序員的介入,有時甚至不需要程序員了解。因此,它們被稱作隱式轉換(implicitconversion)。算術類型之間的隱式轉換被設計得盡可能避免損失精度。很多時候,如果表達式中既有整數類型的運算對象也有浮點數類型的運算對象,整型會轉換成浮點型。在上面的例子中,3轉換成double類型,然后執行浮點數加法,所得結果的類型是double。接下來就要完成初始化的任務了。在初始化過程中,因為被初始化的對象的類型無法改變,所以初始值被轉換成該對象的類型。仍以這個例子說明,加法運算得到的double類型的結果轉換成int類型的值,這個值被用來初始化ival。由double向int轉換時忽略掉了小數部分,上面的表達式中,數值6被賦給了ival。

何時發生隱式類型轉換

  • 在下面這些情況下,編譯器會自動地轉換運算對象的類型:
  • 在大多數表達式中,比int類型小的整型值首先提升為較大的整數類型。
  • 在條件中,非布爾值轉換成布爾類型。
  • 初始化過程中,初始值轉換成變量的類型;在賦值語句中,右側運算對象轉換成左側運算對象的類型。
  • 如果算術運算或關系運算的運算對象有多種類型,需要轉換成同一種類型。
  • 如第6章將要介紹的,函數調用時也會發生類型轉換。

4.11.1算術轉換

  • 算術轉換(arithmeticconversion)的含義是把一種算術類型轉換成另外一種算術類型,這一點在2.1.2節(第32頁)中已有介紹。算術轉換的規則定義了一套類型轉換的層次,其中運算符的運算對象將轉換成最寬的類型。例如,如果一個運算對象的類型是long double,那么不論另外一個運算對象的類型是什么都會轉換成long double。還有一種更普遍的情況,當表達式中既有浮點類型也有整數類型時,整數值將轉換成相應的浮點類型。

整型提升

  • 整型提升 ,負責把小整數類型轉換成較大的整數類型。對于bool、char、signedchar、unsignedchar、short和unsignedshort等類型來說,只要它們所有可能的值都能存在int里,它們就會提升成int類型;否則,提升成unsigned int類型。就如我們所熟知的,布爾值false提升成0、true提升成1。較大的char類型(wchar_t、charl6_t、char32_t)提升成int、unsignedint、long、unsigned long、long long和unsigned long long中最小的一種類型,前提是轉換后的類型要能容納原類型所有可能的值。

無符號類型的運算對象

  • 如果某個運算符的運算對象類型不一致,這些運算對象將轉換成同一種類型。但是如果某個運算對象的類型是無符號類型,那么轉換的結果就要依賴于機器中各個整數類型的相對大小了。像往常一樣,首先執行整型提升。如果結果的類型匹配,無須進行進一步的轉換。如果兩個(提升后的)運算對象的類型要么都是帶符號的、要么都是無符號的,則小類型的運算對象轉換成較大的類型。
  • 如果一個運算對象是無符號類型、另外一個運算對象是帶符號類型,而且其中的無符號類型不小于帶符號類型,那么帶符號的運算對象轉換成無符號的。例如,假設兩個類型分別是unsigned int和int,則int類型的運算對象轉換成unsigned int類型。需要注意的是,如果int型的值恰好為負值,其結果將以2.1.2節(第32頁)介紹的方法轉換,并帶來該節描述的所有副作用。
  • 剩下的一種情況是帶符號類型大于無符號類型,此時轉換的結果依賴于機器。如果無符號類型的所有值都能存在該帶符號類型中,則無符號類型的運算對象轉換成帶符號類型。如果不能,那么帶符號類型的運算對象轉換成無符號類型。例如,如果兩個運算對象的類型分別是long和unsigned int,并且int和long的大小相同,則long類型的運算對象轉換成unsignedint類型;如果long類型占用的空間比int更多,則unsigned int類型的運算對象轉換成long類型。

理解算術轉換

  • 要想理解算術轉換,辦法之一就是研究大量的例子:

  • 在第一個加法運算中,小寫字母,a,是char型的字符常量,它其實能表示一個數字值(參見2.1.1節,第30頁)。到底這個數字值是多少完全依賴于機器上的字符集,在我們的環境中,a,對應的數字值是97。當把,a,和一個longdouble類型的數相加時,char類型的值首先提升成int類型,然后int類型的值再轉換成longdouble類型。最終我們把這個轉換后的值與那個字面值相加。最后的兩個含有無符號類型值的表達式也比較有趣,它們的結果依賴于機器

4.11.2其他隱式類型轉換

  • 除了算術轉換之外還有幾種隱式類型轉換,包括如下幾種。
  • 數組轉換成指針:在大多數用到數組的表達式中,數組自動轉換成指向數組首元素的指針:

  • 當數組被用作decltype關鍵字的參數,或者作為取地址符(&)、sizeof及typeid(第19.2.2節,732頁將介紹)等運算符的運算對象時,上述轉換不會發生。同樣的,如果用一個引用來初始化數組(參見3.5.1節,第102頁),上述轉換也不會發生。我們將在6.7節(第221頁)看到,當在表達式中使用函數類型時會發生類似的指針轉換。
  • 指針的轉換:C++還規定了幾種其他的指針轉換方式,包括常量整數值0或者字面值nullptr能轉換成任意指針類型;指向任意非常量的指針能轉換成void*;指向任意對象的指針能轉換成const void*.15.2.2節(第530頁)將要介紹,在有繼承關系的型間還有另外一種指針轉換的方式。

4.11.3顯式轉換

  • 有時我們希望顯式地將對象強制轉換成另外一種類型。例如,如果想在下面的代碼中執行浮點數除法:
  • int i,j;? ?double? ?slope? = i/j;
  • 就要使用某種方法將i和/或j顯式地轉換成double,這種方法稱作強制類型轉換(cast)
  • 然有時不得不使用強制類型轉換,但這種方法本質上是非常危險的

命名的強制類型轉換

  • 一個命名的強制類型轉換具有如下形式:
  • cast-name<type> (expression); 其中,type是轉換的目標類型而expression是要轉換的值。如果是引用類型 ,則結果是左值 。?cast-name是static cast、dynamic cast、const cast和
    reinterpret_cast中的一種。dynamic_cast支持運行時類型識別,我們將在19.2節(第730頁)其做更詳細的介紹。cast-name指定了執行的是哪種轉換。

reinterpret__cast

  • reinterpret_cast通常為運算對象的位模式提供較低層次上的重新解釋。舉個例子,假設有如下的轉換

  • reinterpret_cast本質上依賴于機器。要想安全地使用reinterpret_cast必須對涉及的類型和編譯器實現轉換的過程都非常了解;

?4 . 1 2 運算符優先級表

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446654.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446654.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446654.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git 之 git tag標簽使用

目錄一、簡介二、本地tag操作1、創建tag標簽&#xff08;1&#xff09;創建輕量標簽&#xff08;2&#xff09;創建附注標簽2、查看tag標簽&#xff08;1&#xff09;查看標簽列表&#xff08;2&#xff09;查看標簽提交信息&#xff08;3&#xff09;在提交歷史中查看標簽3、刪…

codeforces 110A-C語言解題報告

110A題目網址 題目解析 1.輸入一個數字,如果數字中包含的4,7的數量是4或7的倍數,則輸出YES,否則輸出NO 舉例: 輸入: 40047 輸出: NO 2.注意點: 1)由于數字很長,所以使用long long int類型,使用scanf("%lld",&n)接收輸入 2)整型轉字符串,使用sprintf(字符串,“…

C++primer 第 5 章語句 5.2語句作用域 5.3條件語句 5 . 4 迭代語句 5.5跳轉語句 5.6 try語句塊和異常處理

5 . 1 簡單語句 C語言中的大多數語句都以分號結束&#xff0c;一個表達式&#xff0c;比如ival 5 , 末尾加上分號就變成了表達式語句(expression statement)。表達式語句的作用是執行表達式并丟棄掉求值結果&#xff1a;ival 5&#xff1b; // 一條沒什么實際用處的表達式語…

英語口語-文章朗讀Week9Thursday

英語文章 Everyone has his or her own dreams. Some people wants to be millionaires so they can give many generous donations later; some people want to be scientists so they can bring many conveniences to the world; some people only want to be bus-drivers s…

操作系統 內存管理相關知識

cpu執行程序的基本過程 譯碼器 輸入為n管腳&#xff0c;輸出為2^n根管腳&#xff0c;編號為從0到2^(n-1)&#xff0c;用少的輸入端控制更多的輸出端最常用的是三八譯碼器AD(Address bus)地址總線: 選中一行數據每一行 8bit 組成8吧B cpu輸入端32根線&#xff0c;輸出端就可以控…

2000年考研英語閱讀理解文章四

文章詳細解析網址 注意點 1.注意But,however等表示觀點看法轉折的詞語 2.全篇都在提及moral decline 道德下降,最后一段寫that may have more to do with life-style所以造成現象的原因應該是life-style.(主要) 前面都是在分析,最后一段點名原因 知識點 ----單詞 envy n/v…

Chrome瀏覽器必裝插件!尤其程序猿!

Chrome 瀏覽器有一個好處&#xff0c;就是插件極其豐富&#xff0c;只有你想不到的&#xff0c;沒有你找不到的&#xff0c;這恐怕是 Chrome 瀏覽器被眾多愛好者鐘愛的原因吧。 言歸正傳&#xff0c;今天來給大家推薦 10 款我自己珍藏的 Chrome 瀏覽器插件。 1、crxMouse Ch…

codeforces 160A-C語言解題報告

160A題目網址 題目解析 1.輸入硬幣的個數,分配硬幣,使拿最小的硬幣數比剩下的硬幣金額大 舉例: 輸入: 2 3 3 輸出 2 2.注意點: 1)接收整型數組時要使用&,因為只有字符數組是使用指針傳遞首地址的 scanf("%d",&a[i]); 2)使用冒泡排序,將數組從大到小排序…

英語口語-文章朗讀Week10 Monday

英語文章 Here are some valuable suggestions which may assist you in landing good job First, make your resume clear and associate it with the position you are applying for. Try to add details like your temporary jobs at college or your former jobs Second, …

論文遇到的格式問題和修正方式

word空格出現小圓點怎么辦論文參考文獻批量改為上角標&#xff0c;簡單好用&#xff01;&#xff01;&#xff01;字數統計網站word封面下劃線怎么對齊&#xff08;非常簡單徹底解決&#xff09;

codeforces 41A-C語言解題報告

41A題目網址 題目解析 1.輸入一個字符串,如果第二行是倒序輸入這個字符串的,就輸出YES,否則輸出NO 舉例: 輸入: abb aba 輸出: NO 2.倒序輸出時,使用int jstrlen(t)-1;,因為strlen()是計算字符個數,而字符串是從0開始,最后一位是字符串長度減一 3.在接收第二個字符串輸入時…

Linux查看文件的首個字母 文件屬性字段

-rw-r–r– 1 root root 762 07-29 18:19 exit文件屬性字段總共有10個字母組成&#xff1b;第一個字符代表文件的類型。 文件屬性字段 字母“-”表示該文件是一個普通文件字母“d”表示該文件是一個目錄&#xff0c;字母”d”&#xff0c;是dirtectory(目錄)的縮寫&#xff1b…

英語口語-文章朗讀Week10 Wednesday

英語文章 Everyone needs sleep for survival, but how much? It is said that eight hours of sleep is fundamental to a healthy person. But today, many people are sacrificing their sleep time。 Modern people have so many alternatives: cell phones, PCs, TVs, g…

嵌入式Linux多任務編程 進程 管道 命名管道

進程 進程是一個可并發執行的具有獨立功能的程序關于某個數據集合的一次執行過程&#xff0c;也是操作系統執行資源分配和保護的基本單位。程序的一次執行就是一個進程一個程序可以派生多個進程多個不同程序運行的時候&#xff0c;也會有多個相對應的進程與其相互對應進程是動…

2000年考研英語閱讀理解文章五

文章詳細解析網址 知識點 ----單詞 vitality n生命力 hypocritical adj偽善的 pushing adj有進取心的 acquisitive adj渴望獲得的,貪得無厭的 confess v供認,坦白 vulgar adj粗俗的 spectacle n場面,奇觀 participatory adj供分享的 democracy n民主,民主制,民主國家 stir v攪…

英語口語-文章朗讀Week10 Thursday

英語文章 There are many customs and traditions in Chinese civilization. Here, we will talk about the development of the way people greet each other: In ancient times, people had to kneel to those who were superior to them. This custom remained until the …

Linux進程之間通信 信號

2) SIGINT 程序終止(interrupt)信號, 在用戶鍵入INTR字符(通常是Ctrl-C)時發出&#xff0c;用于通知前臺進程組終止進程。 3) SIGQUIT 和SIGINT類似, 但由QUIT字符(通常是Ctrl-\)來控制. 進程在因收到SIGQUIT退出時會產生core文件, 在這個意義上類似于一個程序錯誤信號。 15)…

c++面向對象高級編程 學習一 不帶指針的類

復數類 complex 是一個不帶指針的類&#xff0c;其聲明如下&#xff1a; class complex { public: complex(double r0,double i0):re(r),im(i){} complex& operator (const complex&); double real()const{return re;} double imag()const{return im;}private: double…