(* ++ argv)和while(c = * ++ argv )之间的区别
我有以下代码片段:
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 **
-remember,函数中的数组参数与指针相同。 在程序调用时,事情看起来像这样:
+---+ +---+---+---+---+---+ 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
的指针。 最后,我们取这个字符串的第一个字符( (*++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 +---+
这有帮助吗?
增加argv是一个非常糟糕的主意,因为一旦你这样做,很难获得原始值。 使用整数索引更简单,更清晰,更好 – 毕竟argv是一个数组!
要回答你的问题,++ argv会增加指针。 然后将其应用于间接以获取第一个字符。
是的,你是对的。
while(--argc > 0 && (*++argv)[0] == '-')
正在逐个扫描命令行参数的数组(长度为argc),寻找以-
选项前缀开头的数组。 对于每一个:
while(c = *++argv[0])
正在扫描当前参数中第一个-
后面的开关字符集(即t
和n
,直到它到达字符串null终止符\0
,它终止while循环,因为它的计算结果为false。
这种设计允许两者
myApp -t -n
和
myApp -tn
工作和被理解为有选项t
和n
。
括号更改表达式的计算顺序。
没有括号*++argv[0]
:
-
argv[0]
获取指向argv
当前指向的字符数据的指针。 -
++
将指针增加到字符数组中的下一个字符。 -
*
获得角色。
括号(*++argv)[0]
:
-
++argv
将argv指针递增为指向下一个参数。 -
*
defereferences它获取指向字符数据的指针。 -
[0]
获取字符数组中的第一个字符。
是的,这两个表达式有所不同(尽管只是略有不同)。 IMO,这段代码有点过于聪明。 你最好用这样的东西:
for (int i=1; i
这几乎与上面的代码相同,但我怀疑任何人(谁知道C)都会有任何困难,弄清楚它到底是做什么的。