Chapter 5: Typedefs
第5章: Typedefs
Please don't use things like "vps_t".
請不要使用像 " vps_ t" 這種東西。
It's a _mistake_ to use typedef for structures and pointers. When you see a
它是一個 _錯誤_ 把typedef用於結構和指標。當你看見a時
vps_t a;
in the source, what does it mean?
在程式碼中,它是什麼意思呢?
In contrast, if it says
相反的,如果它寫成
struct virtual_container *a;
you can actually tell what "a" is.
現在你能立刻的告訴我,"a" 是甚麼了吧。
Lots of people think that typedefs "help readability". Not so. They are useful only for:
許多人以為那typedef "幫助可讀性"。但並非如此。他們只有用在:
(a) totally opaque objects (where the typedef is actively used to _hide_
what the object is).
(a) 完全不透明的物件 (於此typedef被主動用於 _隱藏_ 此物件為何) 。
Example: "pte_t" etc. opaque objects that you can only access using
the proper accessor functions.
例:如 "pte_t" 這類不透明的物件,只能使用較適當的存取函式來存取。
NOTE! Opaqueness and "accessor functions" are not good in themselves.
The reason we have them for things like pte_t etc. is that there
really is absolutely _zero_ portably accessible information there.
注意!不透明性與 "存取函式" 它們本身並非好事。
如pte_t這類物件之所以會存在,是因為於此處實在完全 _零_
可攜可存取的資訊。
(b) Clear integer types, where the abstraction _helps_ avoid confusion
whether it is "int" or "long".
(b) 清楚易懂的整數資料型別,利用抽象的概念去 _幫助_ "int" 或者
"long" 避免混淆。
u8/u16/u32 are perfectly fine typedefs, although they fit into
category (d) better than here.
u8/u16/u32是非常好的typedef,雖然在 (d) 項裡面談到的
typedef比較好。
NOTE! Again - there needs to be a _reason_ for this. If something is
"unsigned long", then there's no reason to do
注意! 再說一次 – 一定要有一個 _理由_ 對應,假如本來就是
"unsigned long",那就沒有什麼理由這樣做。
typedef unsigned long myflags_t;
but if there is a clear reason for why it under certain circumstances
might be an "unsigned int" and under other configurations might be
"unsigned long", then by all means go ahead and use a typedef.
但是假如有一個很明確的理由說明為什麼myflags_t在一定的情況下
可能是 "unsigned int" 且在其他情況下有可能是 "unsigned long",
如此當然可以繼續使用typedef。
(c) when you use sparse to literally create a _new_ type for type-checking.
(c) 當你使用稀疏字面上創造一個 _新_ 的型別來做型別檢查。
(d) New types which are identical to standard C99 types, in certain
exceptional circumstances.
(d) 新的資料型別在某些特殊情況下裡與標準C99的型別是相同的。
Although it would only take a short amount of time for the eyes and
brain to become accustomed to the standard types like 'uint32_t',
some people object to their use anyway.
雖然將花費較短的時間讓眼睛和大腦習慣於那些標準資料型別像
'uint32_t' 一樣,無論如何,有一些人反對使用它們。
Therefore, the Linux-specific 'u8/u16/u32/u64' types and their
signed equivalents which are identical to standard types are
permitted -- although they are not mandatory in new code of your
own.
因此,Linux制訂一組與標準型態完全相同的 'u8/u16/u32/u64'
型態是可以容許使用在原始碼,雖然他們並沒有要求你的程式碼
需要一致。
When editing existing code which already uses one or the other set
of types, you should conform to the existing choices in that code.
當你在編輯一份已經有使用過其他型態設定的程式碼時,應該要讓
它保持一致性。
(e) Types safe for use in userspace.
(e) 為了在userspace使用安全的資料型別。
In certain structures which are visible to userspace, we cannot
require C99 types and cannot use the 'u32' form above. Thus, we
use __u32 and similar types in all structures which are shared
with userspace.
在某些userspace可見之structure中,我們無法要求C99 types
也無法使用 'u32' 。因此,我們使用__u32和類似的型態於所有與
userspace共有的structure中。
Maybe there are other cases too, but the rule should basically be to NEVER EVER use a typedef unless you can clearly match one of those rules.
或許也有其他一樣的情況,但是規則應該基本上是從未使用typedef,除非你能清楚與那些規章之一相配。
In general, a pointer, or a struct that has elements that can reasonably be directly accessed should _never_ be a typedef.
一般而言,指標或是資料結構中的元素能被合理的直接存取而且 _決不_ 是一個typedef。
Chapter 6: Functions
第6章: 函式
Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, as we all know), and do one thing and do that well.
函式必須短小可愛,並且只做一件事。它們應該能夠塞進一或兩頁的螢幕裡去 (我們都知道ISO/ANSI標準螢幕大小是80x24) ,且只做一件事,並且要做的好。
The maximum length of a function is inversely proportional to the complexity and indentation level of that function. So, if you have a conceptually simple function that is just one long (but simple) case-statement, where you have to do lots of small things for a lot of different cases, it's OK to have a longer function.
一個函式的 (可允許的) 最大長度是和其複雜度及縮排的程度成反比。所以如果你有一個觀念上簡單的函式,卻是一個長的 (但是簡單的) case敘述,其中你須要對許多不同的情況做許多的小處理,那麼函式長一點沒有關係。
However, if you have a complex function, and you suspect that a less-than-gifted first-year high-school student might not even understand what the function is all about, you should adhere to the maximum limits all the more closely. Use helper functions with descriptive names (you can ask the compiler to in-line them if you think it's performance-critical, and it will probably do a better job of it than you would have done).
不過,如果你有一個複雜的函式,而你覺得可能一般程度的高一學生就無法瞭解這個函式在幹麻,你可能更需要更嚴格的遵守最大長度的限制。使用名字較有意義的輔助函式 (helper functions) (如果這個函式對效率的要求很高的話,你可以要求編譯器把這些輔助函式當作in-line function展開,而且編譯器可能可以做的比你自己手工做來的好) 。
Another measure of the function is the number of local variables. They shouldn't exceed 5-10, or you're doing something wrong. Re-think the function, and split it into smaller pieces. A human brain can generally easily keep track of about 7 different things, anything more and it gets confused. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now.
另外一個評量函式的方法是區域變數的數量。它們不應該超過5-10個,不然你可能做錯了什麼事。重新構思一下這個函式,然後把它切成幾個小塊。人腦一般可以輕易的處理七件事,超過這個數量就會搞亂了。你知道你很聰明,但是兩個禮拜後你可能還想瞭解你現在做了什麼。
In source files, separate functions with one blank line. If the function is exported, the EXPORT* macro for it should follow immediately after the closing function brace line. E.g.:
在程式碼檔案裡,不同的函式用一條空白的行分開。如果函式有被其他的檔案參考到,則EXPORT* 巨集必須緊緊跟隨在函式的右大括號之後。如:
int system_is_up(void)
{
return system_state == SYSTEM_RUNNING;
}
EXPORT_SYMBOL(system_is_up);
In function prototypes, include parameter names with their data types. Although this is not required by the C language, it is preferred in Linux because it is a simple way to add valuable information for the reader.
在函式的原型裡,必須包含了參數名稱以及它們的資料型別。雖然C語言沒有這樣要求,但在Linux的程式碼中是喜歡如此做的,因為這是增加有價值的資訊給讀者的一種簡單方法。
留言列表