第七章

第七章

  • 有符號整數溢出,程序行為是未定義的

  • 無符號整數運算過程中發生溢出,結果是有定義的:對2^n取模,n適用于存儲結果的位數

  • C標準未說明char類型是有符號還是無符號型

  • 「慣用法」

    • while(getchar()!='\n');//skip rest of line
    • while((c=getchar())==' ');//skip blanks
  • C89算術類型

    • 整值類型
      • 字符類型 char
      • 有符號整型 signed charshort intintlong int
      • 無符號整型 unsigned charunsigned shortunsigned intunsigned long
      • 枚舉類型
    • 浮點類型 floatdoublelong double
  • C99算術類型

    • 整數類型
      • 字符類型 char
      • 有符號整型 包括標準的(signed charshort intintlong intlong long int)和擴展的
      • 無符號整型 包括標準的( unsigned charunsigned short intunsigned intunsigned long intunsigned long long int_Bool)和擴展的
      • 枚舉類型
    • 浮點類型
      • 實數浮點類型 floatdoublelong double
      • 復數類型 float_Complexdouble _Complexlong double _Complex
  • 以下情況進行隱式轉換

    • 當算術表達式或邏輯表達式中操作數的類型不相同時(C語言執行所謂的常用算術轉換
    • 當賦值運算符的右側表達式類型與左側變量的類型不匹配時
    • 當函數調用的實參類型與形參類型不匹配時
    • 當return語句中表達式的類型與函數返回值的類型不匹配時
  • 常用算術轉換

    • 整值提升(integral promotion)把字符或短整型轉換成int類型(如果int類型整數沒有大到足以包含所有可能的原始類型值,那么是unsigned int

    • 任一操作數是浮點類型的情況。float->double->long double

    • 兩個操作數均不是浮點類型。首先進行整值提升(保證沒有一個操作數是字符類型或者短整型),然后int-> unsigned int-> long int-> unsigned long int。有一種特殊情況,在unsigned intlong int相同時,如果一個操作數是unsigned int,另一個是 long int,那么都被轉換為unsigned long int

    • 當把有符號操作數和無符號操作數組合時,把有符號操作數“轉換”成無符號的值。轉換過程中需要加上或者減去n+1的倍數,n是無符號類型能表示的最大值。這條規則會導致一些隱蔽的編程錯誤。例:

      #include <stdio.h>
      int main(int argc, char **argv){
          unsigned int a=10;
          int b = -10;
      
          printf("yes, i am %d\n", b < a);
          printf("yes, i am %d\n", -10 < 10);
          return 0;
      }
      

      運行結果是:

      yes, i am 0
      yes, i am 1
      

      結論就是:盡量避免使用無符號整數!

  • 賦值過程中的轉換

    • 常用算術轉換不適用于賦值運算。C語言遵循另一條簡單的轉換規則,那就是把賦值運算符右側的表達式轉換為左側變量的類型
    • 如果變量類型至少和表達式類型一樣寬,那么轉換沒有任何障礙
    • 其他情況是有問題的。把浮點數賦值給整型丟掉小數部分。把某種類型的值賦給類型更狹小的變量時,如果該值在變量類型范圍之外,那么會得到無意義的結果(甚至更糟)
  • C99中的隱式轉換

    • 為了定義轉換規則,C99允許每個整數類型具有“整數轉換等級”。下面是從最高到最低的排序(這里忽略了擴展的整數類型和枚舉類型)
      1. long long intunsigned long long int
      2. long intunsigned long int
      3. intunsigned int
      4. short intunsigned short int
      5. charsigned charunsigned char
      6. _Bool
    • C99用整數提升(integer promotion)取代了C89中的整值提升(integral promotion),可以將任何等級低于intunsigned int的類型轉換為intunsigned int
    • 任一操作數是浮點類型的情況。只要兩個操作數都不是復數類型,float->double->long double
    • 兩個操作數均不是浮點類型。首先進行整數提升,如果兩個操作數類型相同,過程結束。否則一次嘗試以下規則,一旦遇到可應用的規則,就不再考慮其他的規則:
      1. 如果兩個操作數均為有符號型或無符號型,將整數轉換等級低的轉換如為等級高的操作數類型
      2. 如果無符號操作數的等級高于或等于有符號操作數的等級,將有符號操作數轉換為無符號操作數的類型
      3. 如果有符號操作數的類型可以表示無符號操作數類型的所有制,將無符號操作數轉換為有符號操作數的類型
      4. 否則,將兩個操作數都轉換為與有符號操作數的類型相對應的無符號類型
  • 強制類型轉換

    • 有時需要使用強制類型轉換來避免溢出,例:
    long i;
    int j = 1000;
    i = j * j;//overflow may occur
    

    在有些機器上j*j的值過大,無法表示為int型,導致溢出。
    可以改為

    i = (long)j * j;

  • sizeof運算符

    • 編譯器通常就能確定sizeof表達式的值,C99值變長數組不可以。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 國家電網公司企業標準(Q/GDW)- 面向對象的用電信息數據交換協議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,185評論 6 13
  • 變量:在程序中存儲數據項的地方(用序列號指定內存地址)是可以變化的,所以叫做變量(variable)名詞:字節 字...
    全無閱讀 519評論 0 3
  • 如何訪問、如何引用、如何存儲???? 問題:1、如何訪問變量?通過變量名稱來訪問變量2、如何訪問指針變量?通過指針...
    全無閱讀 768評論 0 4
  • 第一類:邏輯型boolean 第二類:文本型char 第三類:整數型(byte、short、int、long) c...
    Jasonme閱讀 1,115評論 0 4
  • 秋 思 曉來秋風起微涼 陌上菊花正欲黃 憑君若問故鄉事 一河濰水清半江
    小女子弘文閱讀 500評論 0 1