Chapter 3: Placing Braces and Spaces
第3章: 括號的擺法
The other issue that always comes up in C styling is the placement of braces. Unlike the indent size, there are few technical reasons to choose one placement strategy over the other, but the preferred way, as shown to us by the prophets Kernighan and Ritchie, is to put the opening brace last on the line, and put the closing brace first, thusly:
C設計風格中另外常被討論的就是括號的位置。不像縮排的案例,選擇括號的擺設沒什麼特別的技術上的理由,但是我較篇好的方式,就像先賢Kernighan和Ritchie所示範給我們看的樣子,是把左大括號放在行尾,然後右大括號放在一行的最前面,就是這樣子:
if (x is true) {
we do y
}
This applies to all non-function statement blocks (if, switch, for, while, do). E.g.:
上述規則適合使用在所有非函式的程式敘述區塊中 (if, switch, for, while, do)。如:
switch (action) {
case KOBJ_ADD:
return "add";
case KOBJ_REMOVE:
return "remove";
case KOBJ_CHANGE:
return "change";
default:
return NULL;
}
However, there is one special case, namely functions: they have the opening brace at the beginning of the next line, thus:
不過,有一個例外,就是函式:函式的左大括號放在次一行的開頭,如下:
int function(int x)
{
body of function
}
Heretic people all over the world have claimed that this inconsistency is ... well ... inconsistent, but all right-thinking people know that (a) K&R are _right_ and (b) K&R are right. Besides, functions are special anyway (you can't nest them in C).
全世界的異議人士總是指出這是種不一致的做法... 嗯... 的確是不太一致,是所有思惟正常的人都知道 (a) K&R是 _對的_ 以及 (b) K&R永遠都是對的。而且,不論如何函式確實是特殊的 (你應該無法將函式寫成巢狀吧!如果你寫的是C) 。
Note that the closing brace is empty on a line of its own, _except_ in the cases where it is followed by a continuation of the same statement, ie a "while" in a do-statement or an "else" in an if-statement, like this:
除非右括號的後面還有未完成的語句,否則右括號應該完全佔有單獨的一行。比如do語句中的 "while" 或者if語句中的 "else",就像這樣︰
do {
body of do-loop
} while (condition);
and
if (x == y) {
..
} else if (x > y) {
...
} else {
....
}
Rationale: K&R.
原因:K&R。
Also, note that this brace-placement also minimizes the number of empty (or almost empty) lines, without any loss of readability. Thus, as the supply of new-lines on your screen is not a renewable resource (think 25-line terminal screens here), you have more empty lines to put comments on.
此外,注意這種擺法使得在不失去可讀性下,空白行 (或者幾乎空白的行) 的數量最少。因此,當螢幕的行數有限的時候 (這裡請考慮25行的螢幕) ,你有較多的空行可以放註解。
Do not unnecessarily use braces where a single statement will do.
不需要使用一個大括號的程式敘述可以寫成這樣。
if (condition)
action();
This does not apply if one branch of a conditional statement is a single statement. Use braces in both branches.
if (condition) {
do_this();
do_that();
} else {
otherwise();
}
3.1: Spaces
Linux kernel style for use of spaces depends (mostly) on function-versus-keyword usage. Use a space after (most) keywords. The notable exceptions are sizeof, typeof, alignof, and __attribute__, which look somewhat like functions (and are usually used with parentheses in Linux, although they are not required in the language, as in: "sizeof info" after "struct fileinfo info;" is declared).
在空格的使用上,Linux核心主要幾乎用於函式對關鍵字的使用上,在關鍵字之後都會使用空格。一些需要注意的例外像是sizeof, typeof, alignof以及__attribute__,這些看起有點像是函式,(通常在Linux裡會用括弧,雖然語言上規定是不需要,像宣告 "struct fileinfo info;",用 "sizeof info" 取得info大小)
So use a space after these keywords:
關鍵字之後會使用空格的有:
if, switch, case, for, do, while
but not with sizeof, typeof, alignof, or __attribute__. E.g.,
關鍵字之後不使用空格的有:sizeof, typeof, alignof or __attribute__。舉例來說:
s = sizeof(struct file);
Do not add spaces around (inside) parenthesized expressions. This example is *bad*:
不要加入空格在有括弧的表示式裡,下面舉個不好的例子:
s = sizeof( struct file );
When declaring pointer data or a function that returns a pointer type, the preferred use of '*' is adjacent to the data name or function name and not adjacent to the type name.
指標的宣告或者有回傳指標的函式, '*' 最好靠近資料或函式名稱,而不要與資料型態相鄰。
Examples:
char *linux_banner;
unsigned long long memparse(char *ptr, char **retptr);
char *match_strdup(substring_t *s);
Use one space around (on each side of) most binary and ternary operators, such as any of these:
兩元或三元運算子前後各使用一個空格,例如下面任一個:
= + - < > * / % | & ^ <= >= == != ? :
but no space after unary operators:
一元運算子之後不加空格:
& * + - ~ ! sizeof typeof alignof __attribute__ defined
no space before the postfix increment & decrement unary operators:
在運算元之後的遞加與遞減運算子前面不加空格:
++ --
no space after the prefix increment & decrement unary operators:
在運算元之前的遞加與遞減運算子後面不加空格:
++ --
and no space around the '.' and "->" structure member operators.
用於結構的運算符號 '.' 和 "->" 前後都不加空格:
Do not leave trailing whitespace at the ends of lines. Some editors with "smart" indentation will insert whitespace at the beginning of new lines as appropriate, so you can start typing the next line of code right away.
However, some such editors do not remove the whitespace if you end up not putting a line of code there, such as if you leave a blank line. As a result, you end up with lines containing trailing whitespace.
不要在行尾加了一連串空格,有些編輯器會 "自動" 的縮排,會在每一行之前先插入幾個空白,這樣子當換行時就能立刻編輯,然而如果你在結束編輯程式碼時留下一行空白行,編輯器並不會 "自動" 清除空格,結果在你結束那幾行就會留下了一連串空格。
Git will warn you about patches that introduce trailing whitespace, and can optionally strip the trailing whitespace for you; however, if applying a series of patches, this may make later patches in the series fail by changing their context lines.
版本控制軟體將會警告你,修正檔有一連串空格的差異,你可以選擇將這些空白刪除;然而經過一系列的修正之後,較後面的修正檔可能會因空格的差異而無法修正內容。
Chapter 4: Naming
第4章: 命名
C is a Spartan language, and so should your naming be. Unlike Modula-2 and Pascal programmers, C programmers do not use cute names like ThisVariableIsATemporaryCounter. A C programmer would call that variable "tmp", which is much easier to write, and not the least more difficult to understand.
C是一個非常簡潔的語言,所以你的命名也要一樣。不像Modula-2和Pascal的程式設計者,C程式設計者不會用像 ThisVariableIsATemporaryCounter 這樣滑稽的名字。一個C程式設計者會叫這個變數 "tmp",不僅較容易寫,並且至少不會比較難以理解。
HOWEVER, while mixed-case names are frowned upon, descriptive names for global variables are a must. To call a global function "foo" is a shooting offense.
不過,雖然不贊成使用混雜大小寫的名字,但是全域變數一定須要具有描述性的名字。叫一個全域函式 "foo" 是一種故意犯錯的行為。
GLOBAL variables (to be used only if you _really_ need them) need to have descriptive names, as do global functions. If you have a function that counts the number of active users, you should call that "count_active_users()" or similar, you should _not_ call it "cntusr()".
全域變數 (僅在必要的時後才使用之) 須要有描述性的名字,就像全域函式一樣. 如果你有一個函式用來數活躍的 (active) 使用者,你應該稱之為 "count_active_users()" 或者類似的名字,不應該稱為 "cntusr()"。
Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged - the compiler knows the types anyway and can check those, and it only confuses the programmer. No wonder MicroSoft makes buggy programs.
把函式的型別編進名字裡面 (所謂的匈牙利表示法,Hungarian notation) 是頭殼壞去的行為 - 無論如何編譯器永遠知道這些形別,而且可以幫你檢查,這種編碼只有令程式設計者更加搞不清楚而已。難怪MicroSoft製造的程式都有很多bug。
LOCAL variable names should be short, and to the point. If you have some random integer loop counter, it should probably be called "i".
Calling it "loop_counter" is non-productive, if there is no chance of it being mis-understood. Similarly, "tmp" can be just about any type of variable that is used to hold a temporary value.
區域變數名字應該要簡短,並且恰到好處。如果你有一些隨意的整數迴圈計數器 (loop counter) ,它應該稱之為 "i"。
如果沒有被混用的困擾的話,叫它 "loop_counter" 是沒有效率的,同樣的,"tmp" 可以是任何的型別的變數,只要是這個變數用來儲存一些暫時的資料。
If you are afraid to mix up your local variable names, you have another problem, which is called the function-growth-hormone-imbalance syndrome.
See chapter 6 (Functions).
如果你怕搞混了你的區域變數的名字,那你遇到另一個問題,被稱為函式成長賀爾蒙失調症。 請參考第6章說明。
留言列表