首先,K & R 1具有在此特定代碼段的勘誤:
117(§5.10):在找到例如,程序增量argv[0]
。這並不是專門禁止的,但也不是特別允許的。
現在解釋。
假設您的程序名爲prog
,並且您執行它:prog -ab -c Hello World
。您希望能夠解析參數,說明指定了選項a
,b
和c
,並且Hello
和World
是非選項參數。
argv
類型char **
—請記住,函數中的數組參數與指針相同。在程序調用,事情是這樣的:
+---+ +---+---+---+---+---+
argv ---------->| 0 |-------->| p | r | o | g | 0 |
+---+ +---+---+---+---+---+
| 1 |-------->| - | a | b | 0 |
+---+ +---+---+---+---+
| 2 |-------->| - | c | 0 |
+---+ +---+---+---+---+---+---+
| 3 |-------->| H | e | l | l | o | 0 |
+---+ +---+---+---+---+---+---+
| 4 |-------->| W | o | r | l | d | 0 |
+---+ +---+---+---+---+---+---+
| 5 |-------->NULL
+---+
這裏,argc
是5,argv[argc]
是NULL
。開始時,argv[0]
是包含字符串"prog"
的char *
。
在(*++argv)[0]
中,由於括號的存在,argv
先遞增,然後解除引用。增量的作用是將該「argv ---------->
」箭頭「向下一塊」移動到指向1
。取消引用的效果是獲取指向第一個命令行參數-ab
的指針。最後,我們取這個字符串的第一個字符([0]
,(*++argv)[0]
),並測試它是否爲'-'
,因爲這表示選項的開始。
對於第二個構造,我們實際上想要走下由當前argv[0]
指針指向的字符串。所以,我們需要把argv[0]
爲指針,忽視了它的第一個字符(即'-'
因爲我們剛剛測試過),並期待在其他字符:
++(argv[0])
將增加argv[0]
,得到一個指向第一個非-
字符,並提領它會給我們這個角色的價值。所以我們得到*++(argv[0])
。但是因爲在C中,[]
比++
結合的更緊密,所以我們實際上可以擺脫括號並得到我們的表達式*++argv[0]
。我們想要繼續處理這個字符,直到它是0
(上圖中每行中的最後一個字符框)。
表達
分配給c
當前選項的價值,並且具有值c
。 while(c)
是while(c != 0)
的簡寫形式,因此while(c = *++argv[0])
行基本上將當前選項的值分配給c
並對其進行測試以查看是否已達到當前命令行參數的末尾。
在這個循環結束時,ARGV將指向第一個非選項參數:
+---+ +---+---+---+---+---+
| 0 |-------->| p | r | o | g | 0 |
+---+ +---+---+---+---+---+
| 1 |-------->| - | a | b | 0 |
+---+ +---+---+---+---+
| 2 |-------->| - | c | 0 |
+---+ +---+---+---+---+---+---+
argv ---------->| 3 |-------->| H | e | l | l | o | 0 |
+---+ +---+---+---+---+---+---+
| 4 |-------->| W | o | r | l | d | 0 |
+---+ +---+---+---+---+---+---+
| 5 |-------->NULL
+---+
這是否幫助?
我也對一件事感興趣: while(c = * ++ argv [0]) 這個表達式。這是否意味着:while(c = * ++ argv [0]!= 0),我的意思是* ++ argv [0]返回一個空指針給c,如果它沒有找到一個字符? – Tool 2010-01-07 14:38:14
是 - 在下面回答。 – 2010-01-07 14:55:54
正如我的回答中所指出的,請參閱K&R在此代碼中的勘誤表條目:http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html – 2010-01-07 15:27:58