編譯器中負責將程序分解為一個一個符號的部分,稱為“詞法分析器”。下面看一個例子:
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);
是等效的。