close

2.1 基本內建型別

C++定義了一組算數型別(arithmetic types),其中有整數、浮點數...。其中有個特殊型別叫void。 void型別沒有相關數值,通常被拿來當作"無返回值"函式的返回型別。

算數型別的"尺碼"(用以表示該型別的位元數)隨機器種類而有所不同。C++ standard保證每個算數型別的最小尺碼,但不禁止compiler使用比較大的尺碼。幾乎所有compiler都使用比要求還大的尺碼來表示int。

8 bits = byte , 4 bytes = word。

short以半個machine word表示、 int 一個machine word、 long為一個或兩個machine word。

如果試著將超出某型別允許範圍的值指派給一個該型別的物件,會發生什麼事? 答案取決於該型別為signed or unsigned。

針對unsigned型別
ex.一個8bits unsigned char物件可存放0~255的值,如果我們將超出範圍的值給它,compiler會把該值除以256所得餘數指派給它。所以如果將336存進一個unsigned char,實際賦值過去的值是80,因為336 % 256 = 80。

Note:
1.在C++,將負數賦值給一個unsigned型別的物件完全合法所得結果是該負數除以"該型別能表現的數目個數"的餘數。
ex. 將-1指派給一個unsigned char,所得結果會是255,因為-1 % 256 = 255。

2.執行整數運算時,short幾乎不會是正確的選擇。在大部分程式中,如果把一個超過short能表示範圍的值塞給short,會導致神秘的臭蟲(bug)。實際上發生什麼事取決於機器,但通常那個值會折回來(wraps around),使一個過大值變成大負數。同樣道理,即使char算是個整數型別,但它仍應該用來存放字元而非計算。char在某些compiler是signed,其它compiler視之為unsigned,這會讓人很囧。所以大部分機器上使用int在整數運算上是比較安全的。

3.決定用哪一種浮點數較簡單,使用double幾乎是對的。float遺失的精準度很顯著,但float跟double在計算上的成本幾乎可被忽略。在某些機器上double可能比float還快。(那以後就都用double就好了)

ex.        跑出來的結果會是 -1 < 5 , why?
#include
int main() {
    int array [] = {1, 2, 3, 4, 5};
    if (-1 < sizeof(array) / sizeof(array[0]))
        printf("-1 < %d\n", sizeof(array) / sizeof(array[0]));
    else
        printf("-1 >= %d\n", sizeof(array) / sizeof(array[0]));
    return 0;
}

ANS:
(1) -1為字面常數,  所以是一個signed int
(2) sizeof() 運算子的回傳值型態為size_t , 實際上被定義為 unsigned int
(3) 兩個unsigned int 相除的結果還是unsigned int
(4) signed int -1和 unsigned int 5比較大小, signed int被提升為unsigned int然後再跟unsigned int 5比較大小
     -1變成被解讀為一個很大的正數, 因此大於usigned int 5

 

2.2字面常數(Literal Constants)

整數字面常數(Integer Literals)規則

三種表示法:
1. 10進位 : 20
2. 8進位 :024 //以0開頭
3. 16進位 : 0x24 //以0x或者0X開頭

浮點字面常數(Floating-Point Literals)規則

可用一般十進位表示法或科學表示法來寫。使用科學表示法,指數以E或e來表示。浮點字面常數的預設型別為double,我們可以在數值後加上F或f指定為單精度,或加上L或l 指定為擴增精度(但不建議用小寫)。

'\0'表示的字元通常稱為null字元。

忠告:  不要倚賴不明確定義的行為(Undefined Behavior),程式如果使用無明確定義的行為,便是犯了錯誤。如果可以成功執行,那只是運氣好塞到。不幸的是,程式如果帶有無明確定義的行為,在某些情況或者某個compiler下或許能夠正確執行,但無法保證在其它compiler下可以正確執行,並且即使可在某組輸入下可以成功,卻不保證在下次的其它輸入中能成功。

 

2.3變數(Variables)

Note:
C++是個靜態型別(statically typed)語言,意思是型別在編譯期被檢查。型別被檢查的過程稱為型別檢驗(type-checking)。隨著程式發展愈來愈複雜,靜態型別檢驗有助於早期找出bug。靜態檢驗的結果是,程式用到的每一個物體(entity)的型別必須被compiler所知。

lvalue : 左值,一個左值算式可出現在賦值操作的左側或右側               // lvalue跟rvalue我看不懂在幹啥
rvalue :右值,一個右值算式只能出現在賦值操作的右側     

變數命名習慣
1.變數名稱通常以小寫字母寫成,例如說temp而不是TEMP
2.識別符號應該是可以幫助記憶的名稱,也就是盡量讓它有意義。例如要表達薪水的變數名稱可以取成salary。
3.多個單字識別符號可以在每個單字之間加上底線,或是第一個以外的單字首字母大寫。例如 student_number 或 studentNumber。

初始化(initialization)

物件如果在一開始在定義時獲得明確初值,稱為已初始化(initialized)。C++支援兩種變數初始化
1.copy-initialized(拷貝初始化)     ex.   int   i = 1024;
2.direct-initialized(直接初始化)   ex.   int  i(1024);

變數初始化規則

當我們定義一個變數而沒有提供初值,系統有時候會自動為我們自動初始化。至於系統提供什麼初值,取決於變數型別以及它所在的位置。

內建型變數會不會自動被初始化與它的位置有關。定義於function主體外的任何變數都會獲得初值0,定義於function內的則沒有初值。因此,除了作為賦值操作的左運算元,其他任何使用未初始化變數的行為都沒有明確定義(也就是一開始最好給初值),由於未將變數初始化而導致的bug很難找出來,所以最好給初值。

當心 : 未初始化變數(Uninitialized Variables)會造成執行期問題
         有時候程式順利執行,並產生錯誤結果。更糟的是在某台機器上正確執行,到另一台卻錯。如果病急亂投醫,在不相干位置加入程式碼,很可能造成原本正確的程式碼產生
   不正確的結果。

(未完)

arrow
arrow
    全站熱搜

    vencees 發表在 痞客邦 留言(0) 人氣()