編譯器中負責將程序分解為一個一個符號的部分,稱為“詞法分析器”。下面看一個例子: if(x > big) big = x; 這個語句的第一個符號是C語言的關鍵字if,緊接著下一個符號是左括號,再下一個符號是標識符x,再下一個是大於號,再下一個是標識符big,依次類推。在C語言中,符號之間的空白符將被忽略。 本章將探討符號和組成符號的字符間的關系,以及有關符號含義的一些常見誤解。 陷阱1 “=”不同於“==” 將相等符號”==”誤寫為賦值符號”=”,是一種容易出現的錯誤,而且不容易檢查出來。來看一個示例程序page6_7.c,其代碼如下: [cpp] 1#include <stdio.h> 2 3int main() 4{ 5 int i, j; 6 i = 10; 7 j = 20; 8 if(i = j) 9 printf("i equal j\n"); 10 11 return 0; 12} 1#include <stdio.h> 2 3int main() 4{ 5 int i, j; 6 i = 10; 7 j = 20; 8 if(i = j) 9 printf("i equal j\n"); 10 11 return 0; 12} 編譯運行效果如下:
本程序第8行,本意是判斷i是否等於j,如果相等則打印語句。現在將”==”誤寫為”=”,語意變成將j的值賦值給i,然後if判斷i的值是否為0。所以,除非j的值為0,否則第8行的if判斷總是為真。做為驗證,可以試試下面的程序運行效果: [cpp] 1#include <stdio.h> 2 3int main() 4{ 5 int i, j; 6 i = 10; 7 j = 0; 8 if(i = j) 9 printf("i equal j\n"); 10 11 return 0; 12} 1#include <stdio.h> 2 3int main() 4{ 5 int i, j; 6 i = 10; 7 j = 0; 8 if(i = j) 9 printf("i equal j\n"); 10 11 return 0; 12} 陷阱2 詞法分析中的“貪心法” C語言中的某些符號,例如/、*、和=,只有一個字符長,稱為單字符符號,還有一些符號,例如/*和==,包含多個字符,稱為多字符符號。當C編譯器讀入一個字符”/”後又讀入一個字符”*”,那麼編譯器就必須做出判斷:是將其作為兩個單字符符號對待還是合起來作為一個字符對待。 C語言對這個問題的解決方案是采用“貪心法”(又稱“大嘴法”):每個符號應該包含盡可能多的字符。 看例子page8_9.c,代碼如下: [cpp] 1#include <stdio.h> 2 3int main() 4{ 5 int a = 10, b=2; 6 printf("a = 10, b = 2, a---b = %d\n", a---b); 7 8 return 0; 9} 1#include <stdio.h> 2 3int main() 4{ 5 int a = 10, b=2; 6 printf("a = 10, b = 2, a---b = %d\n", a---b); 7 8 return 0; 9} 編譯執行結果如下: 第6行,a---b按照貪心法分析,等價於(a--) - b,特別需要注意前面是a--,即先取a的值,再做減1操作,所以10 - 2 = 8。沒運行之前,我認為結果應該是7呢。 陷阱3 整型常量 如果一個整型常量的第一個字符是數字0,那麼該常量將被視作八進制數,因此,11和011的含義截然不同。 看代碼page10_11.c: [cpp] 1#include <stdio.h> 2 3int main() 4{ 5 int a = 11, b = 011; 6 printf("a = %d, b = %d\n", a, b); 7 8 return 0; 9} 1#include <stdio.h> 2 3int main() 4{ 5 int a = 11, b = 011; 6 printf("a = %d, b = %d\n", a, b); 7 8 return 0; 9}編譯執行結果如下: 由執行結果可以看出,011被看作是八進制數,對應的十進制數是9。 陷阱4 字符與字符串 C語言中的單引號與雙引號含義迥異,在某些情況下,如果把兩者弄混,編譯時會出錯,有時編譯器不報錯,從而在運行時產生難以預料的結果。 用單引號括起來的一個字符實際上代表一個整數,整數值對應於該字符在編譯器采用的字符集中的序列值。因此,對於采用ASCII字符集的編譯器而言,’a’的含義與0141(八進制)或者97(十進制)嚴格一致。 用雙引號括起來的字符串,代表的卻是一個指向無名數組起始字符的指針,該數組被雙引號之間的字符以及一個額外的二進制值為0的字符’\0’初始化。 下面這個語句: printf(“Hello world\n”); 與 char hello[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘ ‘, ‘w’, ‘o’, ‘r’, ‘l’, ‘d’, ‘\n’, 0}; printf(hello); 是等效的。