1. 縮進和空白
我們知道C語言的語法對縮進和空白沒有要求,空格、Tab、換行都可以隨意寫,實現同樣功能的代碼可以寫得很好看,也可以寫得很難看。
1.1. 缺少縮進和空白的代碼
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
char gesture[3][10]={"scissor","stone","cloth"};
int man,computer,result, ret;
srand(time(NULL));
while(1){
computer=rand()%3;
printf("\nInput your gesture (0-scissor 1-stone 2-cloth):\n");
ret=scanf("%d",&man);
if(ret!=1||man<0||man>2){
printf("Invalid input!\n");
return 1;
}
printf("Your gesture: %s\tComputer's gesture: %s\n",gesture[man],gesture[computer]);
result=(man-computer+4)%3-1;
if(result>0)printf("You win!\n");
else if(result==0)printf("Draw!\n");
else printf("You lose!\n");
}
return 0;
}一是缺少空白字符,代碼密度太大,看著很費勁。二是沒有縮進,看不出來哪個{和哪個}配對,像這麼短的代碼還能湊合著看,如果代碼超過一屏就完全沒法看了。[CodingStyle]中關於空白字符並沒有特別規定,因為基本上所有的C代碼風格對於空白字符的規定都差不多,主要有以下幾條。
1、關鍵字if、while、for與其後的控制表達式的(括號之間插入一個空格分隔,但括號內的表達式應緊貼括號。例如:
while␣(1);2、雙目運算符的兩側各插入一個空格分隔,單目運算符和操作數之間不加空格,例如i␣=␣i␣+␣1、++i、!(i␣<␣1)、-x、&a[1]等。
3、後綴運算符和操作數之間也不加空格,例如取結構體成員s.a、函數調用foo(arg1)、取數組成員a[i]。
4、,號和;號之後要加空格,這是英文的書寫習慣,例如for␣(i␣=␣1;␣i␣<␣10;␣i++)、foo(arg1,␣arg2)。
5、以上關於雙目運算符和後綴運算符的規則並沒有嚴格要求,有時候為了突出優先級也可以寫得更緊湊一些,例如for␣(i=1;␣i<10;␣i++)、distance␣=␣sqrt(x*x␣+␣y*y)等。但是省略的空格一定不要誤導了讀代碼的人,例如a||b␣&&␣c很容易讓人理解成錯誤的優先級。
6、由於UNIX系統標准的字符終端是24行80列的,接近或大於80個字符的較長語句要折行寫,折行後用空格和上面的表達式或參數對齊,例如:
if␣(sqrt(x*x␣+␣y*y)␣>␣5.0
&&␣x␣<␣0.0
&&␣y␣>␣0.0)再比如:
foo(sqrt(x*x␣+␣y*y),
a[i-1]␣+␣b[i-1]␣+␣c[i-1])7、較長的字符串可以斷成多個字符串然後分行書寫,例如:
printf("This is such a long sentence that "
"it cannot be held within a line\n");C編譯器會自動把相鄰的多個字符串接在一起,以上兩個字符串相當於一個字符串"This is such a long sentence that it cannot be held within a line\n"。
8、有的人喜歡在變量定義語句中用Tab字符,使變量名對齊,這樣看起來很美觀。
→int →a, b;
→double →c;內核代碼風格關於縮進的規則有以下幾條。
1、要用縮進體現出語句塊的層次關系,使用Tab字符縮進,不能用空格代替Tab。在標准的 字符終端上一個Tab看起來是8個空格的寬度,如果你的文本編輯器可以設置Tab的顯示寬度是幾個空格,建議也設成8,這樣大的縮進使代碼看起來非常清 晰。如果有的行用空格做縮進,有的行用Tab做縮進,甚至空格和Tab混用,那麼一旦改變了文本編輯器的Tab顯示寬度就會看起來非常混亂,所以內核代碼 風格規定只能用Tab做縮進,不能用空格代替Tab。
2、if/else、while、do/while、for、switch這些可以帶語句塊的語句,語句塊的{或}應該和關鍵字寫在同一行,用空格隔開,而不是單獨占一行。例如應該這樣寫:
if␣(...)␣{
→語句列表
}␣else␣if␣(...)␣{
→語句列表
}但很多人習慣這樣寫:
if␣(...)
{
→語句列表
}
else␣if␣(...)
{
→語句列表
}內核的寫法和[K&R]一致,好處是不必占太多行,使得一屏能顯示更多代碼。這兩種寫法用得都很廣泛,只要在同一個項目中能保持統一就可以了。
3、函數定義的{和}單獨占一行,這一點和語句塊的規定不同,例如:
int␣foo(int␣a,␣int␣b)
{
→語句列表
}4、switch和語句塊裡的case、default對齊寫,也就是說語句塊裡的case、default標號相對於switch不往裡縮進,但標號下的語句要往裡縮進。例如:
→switch␣(c)␣{
→case 'A':
→ →語句列表
→case 'B':
→ →語句列表
→default:
→ →語句列表
→}用於goto語句的自定義標號應該頂頭寫不縮進,而不管標號下的語句縮進到第幾層。
5、代碼中每個邏輯段落之間應該用一個空行分隔開。例如每個函數定義之間應該插入一個空行,頭文件、全局變量定義和函數定義之間也應該插入空行,例如:
#include <stdio.h>
#include <stdlib.h>
int g;
double h;
int foo(void)
{
→語句列表
}
int bar(int a)
{
→語句列表
}
int main(void)
{
→語句列表
}6、一個函數的語句列表如果很長,也可以根據相關性分成若干組,用空行分隔。這條規定不是嚴格要求,通常把變量定義組成一組,後面加空行,return語句之前加空行,例如:
int main(void)
{
→int →a, b;
→double →c;
→語句組1
→語句組2
→return 0;
}