在 bourne shell(sh) 中,有一個 built-in command:
: A null command that returns a 0 (true) exit value.
只要 shell 執行這個 :,就會直接回傳 0,也就是跟 true 的用法一樣。
所以:
while true; do
...
done
也可以寫成:
while :; do
....
done
更進一步,還可以這樣用:
${parameter:="word"}
ls $parameter
${parameter:="word"} 的意思是給定預設值,如果這是寫在一開始的地方,那就是將 parameter 預設為 word。
但是如果你直接在 script 中寫一行:${parameter:="word"},那將會出現 command not found 的錯誤。因為 sh 會先把 ${...} 替換成 word,然後再執行那行,但是 word 應該不存在,所以就會 command not found。
: ${parameter:="word"}
ls $parameter
如果加上這個 : ,直譯器跑到這行上,還是會像上面一樣,將 parameter 設成 word,並且代換之:
: word
ls $parameter
最後它就是跑這行指令,接著因為遇到了 :,這行指令永遠為 true,並且繼續執行下一行指令。又,parameter 在上一行已經被預設為 word 了,所以這最後的結果就是做 ls word。
簡潔有力的做法:預設值,打鍵數少,程式碼短。
之前記過 FreeBSD nfsd 的服務流程,這邊記得是 FreeBSD mount_nfs 的流程:
mount_nfs 自己會先以 RPC 的 NFS_NULL_PROC 探看 server 的 nfsd。mount_nfs 接著以 RPC 的 RPC_MOUNT 對 server 的 mountd 取得 exported root handle。mount_nfs 將取得的資訊以 iovec 的結構存起來。mount_nfs 最後將這個 iovec 的參數丟進 nmount() system call 進入 kernel mode。 nmount() 訂義在 /usr/src/sys/kern/vfs_mount.c。nmount() 透過 vfs_domount() 呼叫到真正的 VFS_MOUNT()。/usr/src/sys/fs/nfsclient/nfs_clvfsops.c 的 nfs_mount() 做真正的後續。nfs_mount() 做完,就會跟著 nfs_statfs()。nfs_statfs() 裡面,會依序呼叫 FSINFO 與 FSSTAT 這兩個 RPC procedure。所以,這就是為什麼每當 client 做了 mount_nfs 以後,server 那邊收到的記錄是:NULL、FSINFO、FSSTAT。
讀這篇,請先理解如何唸它。
int a[5];
跟
typedef int array[5]; // array: a "type" of array of int
array a;
是同樣效果。現在要宣告一個 function pointer array (void *func())的話:
/* func_pointer_t: a "type" of pointer to function returning pointer to void. */
typedef void *(*func_pointer_t)();
func_pointer_t func_array[] = { (func_pointer_t) open, (func_pointer_t) close };
再混淆一點,多宣告一個 func_array_t 型別
/* func_pointer_t: a "type" of pointer to function returning pointer to void. */
typedef void *(*func_pointer_t)();
/* func_array_t: a "type" of array of pointer to function returning pointer to void */
typedef void *(*func_array_t[])();
func_array_t func_array = { (func_pointer_t) open, (func_pointer_t) close };
或是就很酷的寫
void *(*func_array[])() = { ( (void *(*)()) open, ((void *(*)()) close };
這時候 func_array 就是 an array of pointer to function return pointer to void.
每個元素都是 a pointer to function returning pointer to void.
以上都能達到同樣效果。
當其中加入了 struct 或是 multidimensional array 的時候,情況會更複雜,但是只要知道優先順序(兩種括號優先、再來是星星)、唸法,還是可以輕鬆吃下。
看起來平時用不到,不過透過強制轉型,可以實現型別多型,請參考 rpcgen 產生出的 server code。而這裡講的只是讓作法更簡潔,不用透過一堆的 if 判斷。下次再講。
Usually, a struct-declarator is just a declarator for a member of a structure or union. A structure member may also consist of a specified number of bits. Such a member is also called a bit-field; its length is set off from the declarator for the field name by a colon.
struct-declarator:
declarator declarator : constant-expression
struct {
int a : 1;
}