![](/img/trans.png)
[英]Difference between ++*argv, *argv++, *(argv++) and *(++argv)
[英]Difference between (*++argv)[0] and while(c = *++argv[0])
我有以下代碼片段:
int main(int argc, char *argv[])
{
char line[MAXLINE];
long lineno = 0;
int c, except = 0, number = 0, found = 0;
while(--argc > 0 && (*++argv)[0] == '-') //These two lines
while(c = *++argv[0]) //These two lines
switch(c) {
case 'x':
except = 1;
break;
case 'n':
number = 1;
break;
default:
printf("find: illegal option %c\n", c);
argc = 0;
found = -1;
break;
}
...
}
包含以下表達式:
while(--argc > 0 && (*++argv)[0] == '-')
括號(*++argv)[0]
中的此表達式與不帶括號的while(c = *++argv[0])
有區別嗎?
如果是這樣,怎么辦? (*++argv)
是否表示指向下一個參數的指針, *++argv[0]
表示指向所指向的當前char數組中下一個字符的指針?
首先,K&R在此特定代碼段上有勘誤表:
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]
是一個char *
包含字符串"prog"
。
在(*++argv)[0]
,由於括號的原因, argv
首先遞增,然后取消引用。 增量的作用是將argv ---------->
箭頭“向下移動一格”,指向1
。 解引用的作用是獲得指向第一個命令行參數-ab
的指針。 最后,我們取(第一個字符[0]
中(*++argv)[0]
此字符串的,並對其進行測試,看它是否是'-'
,因為這表示選項的開始。
對於第二種構造,我們實際上想遍歷當前argv[0]
指針所指向的字符串。 因此,我們需要將argv[0]
視為指針,忽略其第一個字符(如我們剛剛測試的'-'
),然后查看其他字符:
++(argv[0])
將使argv[0]
遞增,以獲得指向第一個非-
字符的指針,對其取消引用將為我們提供該字符的值。 這樣我們得到*++(argv[0])
。 但是,由於在C中, []
比++
綁定更緊密,因此我們實際上可以擺脫括號,並將表達式表示為*++argv[0]
。 我們要繼續處理此字符,直到它為0
(上圖中每行的最后一個字符框)為止。
表達方式
c = *++argv[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(--argc > 0 && (*++argv)[0] == '-')
正在掃描(長度的argc的)命令行參數逐一陣列尋找那些開始與-
選項前綴。 對於每個:
while(c = *++argv[0])
正在掃描當前參數中第一個-
后面的開關字符集(即-tn
t
和n
),直到它到達字符串null終止符\\0
為止,該字符串終止while循環,因為它的值為false。
這種設計允許
myApp -t -n
和
myApp -tn
既起作用又被理解為具有選項t
和n
。
遞增argv是一個非常糟糕的主意,因為一旦完成,就很難找回原始值。 使用整數索引更簡單,更清晰,更好-畢竟argv是一個數組!
要回答您的問題,++ argv會增加指針。 然后對它應用了間接獲取第一個字符。
括號會更改表達式的計算順序。
沒有括號*++argv[0]
:
argv[0]
獲取指向argv
當前指向的字符數據的指針。 ++
將該指針增加到字符數組中的下一個字符。 *
獲取角色。 帶括號(*++argv)[0]
:
++argv
將argv指針遞增以指向下一個參數。 *
取消引用它以獲得指向字符數據的指針。 [0]
獲取字符數組中的第一個字符。 是的,這兩個表達式有所不同(盡管只有一點點)。 IMO,此代碼有點過於聰明。 最好使用以下方法:
for (int i=1; i<argc; i++)
if (argv[i][0] == '-') {
size_t len = strlen(argv[i]);
for (int j=0; j<len; ++j)
switch(argv[i][j]) {
case 'x':
// ...
這幾乎等同於上面的代碼,但是我懷疑任何人(完全了解C)是否會真正了解它的實際作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.