簡體   English   中英

(* ++ argv)[0]和while(c = * ++ argv [0])之間的區別

[英]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 您希望能夠解析參數以說指定了選項abc ,而HelloWorld是非選項參數。

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 tn ),直到它到達字符串null終止符\\0為止,該字符串終止while循環,因為它的值為false。

這種設計允許

myApp -t -n

myApp -tn

既起作用又被理解為具有選項tn

遞增argv是一個非常糟糕的主意,因為一旦完成,就很難找回原始值。 使用整數索引更簡單,更清晰,更好-畢竟argv是一個數組!

要回答您的問題,++ argv會增加指針。 然后對它應用了間接獲取第一個字符。

括號會更改表達式的計算順序。

沒有括號*++argv[0]

  1. argv[0]獲取指向argv當前指向的字符數據的指針。
  2. ++將該指針增加到字符數組中的下一個字符。
  3. *獲取角色。

帶括號(*++argv)[0]

  1. ++argv將argv指針遞增以指向下一個參數。
  2. *取消引用它以獲得指向字符數據的指針。
  3. [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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM