C 語言基礎教程(我的C之旅開始了)[五]

來源:互聯網
上載者:User

12. 基礎資料型別 (Elementary Data Type):整型(下)

1. 輸出各種整數類型的變數

輸出不同類型的整數,需要使用不用的格式限定符。輸出 unsigned int 類型的整數,要用 %u 。輸出 long ,要用 %ld;如果要以十六進位或者八進位形式輸出,那就用 %lx(或者%lX)或者 %lo。注意:雖然整數常量的尾碼使用大寫或者小寫英文字母都沒關係,但是它們格式限定符必須使用小寫!如果我們要輸出 short 類型的整數,可以在 %d 中間加上首碼 h,也就是%hd;同理,%ho%hx(或者 %hX )分別表示以八進位或十六進位形式輸出。首碼 hl 可以和 u 組合,表示輸出不帶正負號的整數。例如:%lu 表示輸出 unsigned long 類型的整數;%hu 表示輸出unsigned short類型的整數。如果您的編譯器支援C99,可以使用 %lld%llu 分別表示輸出 long long 和 unsigned long long 。下面我們來看一個輸出各種類型整數的程式:

#include <stdio.h>

int main(void)
{
unsigned int un = 3000000000; /* 我使用的編譯器 int 是 32 位的 */
short end = 200; /* 而 short 是 16 位的 */
long big = 65537;

printf("un = %u and not %d\n", un, un);
printf("end = %hd and %d\n", end, end);
printf("big = %ld and not %hd\n", big, big);

printf("Press ENTER to quit...");
getchar();
return 0;
}

使用 Dev-C++ 編譯運行這個程式輸出結果如下:

un = 3000000000 and not -1294967296
end = 200 and 200
big = 65537 and not 1
Press ENTER to quit...

這個程式表明,錯誤使用格式限定符會導致意想不到的輸出。首先,錯誤使用 %d 來做無符號整型變數 un 的格式限定符,導致輸出的是負數。這是因為我的電腦使用相同的二進位形式來表示 3000000000 和 -129496296 ,而電腦只認識二進位。所以,如果我們使用 %u 告訴 printf 輸出不帶正負號的整數,輸出的就是 3000000000;如果我們誤用了 %d,那麼輸出的就是一個負數。不過,如果我們把代碼中的 3000000000 改成 96 的話,輸出就不會出現異常。因為 96 沒有超出 int 的表示範圍。
然後,對於第二個 printf,無論我們使用 %hd 還是 %d,輸出的結果都是一樣的。這是因為 C 語言標準規定,當 short 類型值傳遞給函數時,要自動轉化成 int 類型值。之所以轉化成 int,是因為 int 被設計為電腦處理效率最高的整數類型。所以,對於 short 和 int 大小不同的電腦來說,把變數 end 轉化成 int 類型再傳遞給函數,速度更快。如此說來,h 好像沒有存在意義。其實不然。我們可以用 %hd 來看看較大的整數類型被截斷成 short 類型的時候會是什麼樣的。
而第三個printf,由於誤用%hd,導致輸出是1。這是因為,如果long是32位的話,65537的二進位形式便是 0000 0000 0000 0001 0000 0000 0000 0001,而 %hd 命令 printf 輸出 short 類型的值,從而導致 printf 只對後 16 位進行處理,最終導致輸出 1。
在前面的教程裡,我們說過,保證格式限定符的數目和參數數目一致是我們的責任。同樣,保證格式限定符的類型和參數類型一致也是我們的責任!正如上面所說的那樣,錯誤使用格式限定符會導致意想不到的輸出!

2. 整數溢出

首先請看以下程式:

#include <stdio.h>

int main(void)
{
/* 32 位 int 表示範圍的上限和下限 */
int i = 2147483647, j = -2147483648;
unsigned int k = 4294967295, l = 0;

printf("%d %d %d %d\n", i, i+1, j, j-1);
printf("%u %u %u %u %u\n", k, k+1, k+2, l, l-1);

printf("Press ENTER to quit...");
getchar();
return 0;
}

使用 Dev-C++ 編譯運行這個程式輸出結果如下:

2147483647 -2147483648 -2147483648 2147483647
4294967295 0 1 0 4294967295
Press ENTER to quit...

這個程式中,i+1 是負數,j-1 是正數,k+1 是 0,l-1 是 4294967295 。這是因為加減運算過後,它們的值超出了它們對應的那種整數類型的表示範圍,我們把這種現象稱為溢出
unsigned int 型變數的值如果超過了上限,就會返回 0,然後從 0 開始增大。如果小於 0,那麼就會到達 unsigned 型的上限,然後從上限開始減小。就好像一個人繞著跑道跑步一樣,繞了一圈,又返回出發點。int 型變數溢出的話,會變成負數,或者正數。
對於 unsigned 類型的整數,它們溢出時的情況一定和上面描述的一樣,這是標準規定的。但是標準並沒有規定有符號整數溢出時會出現什麼情況。這裡描述的有符號整數溢出時出現的情況是最常見的,但是在別的電腦,使用別的編譯器,也可能出現不同的情況。

13. 標識符命名規則

1. 長度限制

C89 規定,編譯器至少應該能夠處理 31 個字元(包括 31)以內的內部標識符(internal identifier);而對於外部標識符(external identifier),編譯器至少應該能夠處理 6 個字元(包括 6)以內的外部標識符。所謂標識符,是指我們為變數(variable)、宏(macro),或者函數(function)等等取的名字。例如 int num; 這個語句中的 num 就是一個標識符。
最新的 C99 標準規定,編譯器至少應該能夠處理 63 個字元(包括 63)以內的內部標識符;編譯器至少應該能夠處理 31 個字元(包括 31)以內的外部標識符。
事實上,我們可以使用超出最大數目限制的字元來命名標識符,不過編譯器會忽略超出的那部分字元。也就是說,如果我們用 35 個字元來命名變數,而那個編譯器最多隻能處理 31 個字元的變數名的話,那麼多出的那 4 個字元就會被編譯器忽略,只有前面的 31 個字元有效。有些古老的編譯器只能處理 8 個字元以內的標識符,對於這樣的編譯器來說,標識符 kamehameha 和 kamehameko 是等價的,因為它們前面 8 個字元相等。

2. 可用字元和組合規則

標準規定,標識符只能由大小寫英文字母底線(_),以及阿拉伯數字組成。標識符的第一個字元必須是大小寫英文字母或者底線,而不能是數字。

合法命名 非法命名
wiggles      $Z]** /*      $、] 和 * 都是非法字元 */
cat2 2cat /* 不能以數字開頭 */
Hot_Tub Hot-Tub /* - 是非法字元 */
taxRate tax rate /* 不能有空格 */
_kcab don't /* ' 是非法字元 */

作業系統和 C 語言標準庫裡的標識符一般以底線開頭,這是約定俗成的。因此,我們應該避免使用底線作為我們自己定義的標識符的開頭。
C 語言是大小寫敏感的語言,也就是說,star、Star、sTar,stAr 和 STAR 等都是相互不同的標識符。
我們不能用關鍵字保留標識符來給我們自訂的變數命名。關於關鍵字和保留標識符,請點擊 關鍵字和保留標識符

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.