程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C陷阱與缺陷代碼分析之第1章詞法陷阱

C陷阱與缺陷代碼分析之第1章詞法陷阱

編輯:關於C
編譯器中負責將程序分解為一個一個符號的部分,稱為“詞法分析器”。下面看一個例子:   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);   是等效的。  
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved