代码之家  ›  专栏  ›  技术社区  ›  Tool

(++argv)[0]和while(c=*++argv[0])之间的差异

  •  13
  • Tool  · 技术社区  · 16 年前

    我有以下代码片段:

    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数组中被指向的下一个字符的指针?

    5 回复  |  直到 11 年前
        1
  •  40
  •   Alok Singhal    16 年前

    首先,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 . 开始的时候, AGV〔0〕 是一个 char * 包含字符串 "prog" .

    (*++argv)[0] 因为括号, 阿尔加夫 先递增,然后取消引用。增量的效果是移动 argv ----------> 箭头“向下一个街区”,指向 1 . 取消引用的效果是获取指向第一个命令行参数的指针, -ab .最后,我们选第一个角色( [0] 在里面 (*+ARGV)〔0〕 )测试这个字符串,看它是否 '-' 因为这表示选项的开始。

    对于第二个构造,我们实际上希望沿着当前 AGV〔0〕 指针。所以,我们需要治疗 AGV〔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
                     +---+
    

    这有帮助吗?

        2
  •  5
  •   anon    16 年前

    增加argv是一个非常糟糕的主意,因为一旦这样做了,就很难恢复原始值。使用整数索引更简单、更清晰、更好——毕竟argv是一个数组!

    要回答您的问题,++argv会增加指针。然后对其应用间接寻址以获取第一个字符。

        3
  •  5
  •   Alex Brown    16 年前

    是的,你是对的。

    while(--argc > 0 && (*++argv)[0] == '-')
    

    正在逐个扫描命令行参数的数组(长度为argc),以查找以 - 选项前缀。对于每一项:

    while(c = *++argv[0])
    

    正在扫描第一个字符后面的一组开关字符 - 在当前的论点中(即 t n 在里面 -tn ,直到它碰到字符串空终止符 \0 ,终止while循环,因为它的计算结果为false。

    这种设计允许

    myApp -t -n
    

    myApp -tn
    

    对工作和被理解为有选择 T N号 .

        4
  •  4
  •   Dave Cluderay    16 年前

    括号更改表达式的计算顺序。

    不带括号 *++argv[0] :

    1. argv[0] 获取指向当前由指向的字符数据的指针 argv .
    2. ++ 将指针递增到字符数组中的下一个字符。
    3. * 获取角色。

    带圆括号 (*++argv)[0] 以下内容:

    1. ++argv 增加argv指针指向下一个参数。
    2. * 将其延迟以获取指向字符数据的指针。
    3. [0] 获取字符数组中的第一个字符。
        5
  •  2
  •   Jerry Coffin    16 年前

    是的,这两个表达式有点不同(尽管只有一点点)。在我看来,这段代码有点过于聪明了。你最好这样做:

    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)都很难弄清楚它到底做了什么。

    推荐文章