首先,K&R 对此特定片段有一个勘误表:
117(§5.10):在find示例中,程序递增argv[0]
. 这没有特别禁止,但也没有特别允许。
现在解释一下。
假设您的程序名为prog
,并且您使用以下命令执行它:prog -ab -c Hello World
。您希望能够解析参数以说明 options a
, b
andc
被指定,并且Hello
andWorld
是非选项参数。
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"
。
In (*++argv)[0]
,因为有括号,argv
首先递增,然后取消引用。增量的效果是将该argv ---------->
箭头“向下移动一个块”,指向1
. 取消引用的效果是获得指向第一个命令行参数的指针,-ab
. 最后,我们取这个字符串的第一个字符 ( [0]
in (*++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
+---+
这有帮助吗?