[英]Difference between (*++argv)[0] and while(c = *++argv[0])
I have the following snippet of code: 我有以下代码片段:
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;
}
...
}
Containing the following expressions: 包含以下表达式:
while(--argc > 0 && (*++argv)[0] == '-')
Does this expression in the parentheses (*++argv)[0]
differ from while(c = *++argv[0])
without parentheses? 括号
(*++argv)[0]
中的此表达式与不带括号的while(c = *++argv[0])
有区别吗?
If so, how? 如果是这样,怎么办? Does
(*++argv)
mean pointer to the next argument, and does *++argv[0]
mean pointer to the next character in the current char array which is being pointed to? (*++argv)
是否表示指向下一个参数的指针, *++argv[0]
表示指向所指向的当前char数组中下一个字符的指针?
First, K&R have an errata on this particular snippet: 首先,K&R在此特定代码段上有勘误表:
117(§5.10): In the find example, the program increments
argv[0]
.117(§5.10):在查找示例中,程序将
argv[0]
递增。 This is not specifically forbidden, but not specifically allowed either.这不是明确禁止的,但也没有明确允许。
Now for the explanation. 现在进行解释。
Let's say your program is named prog
, and you execute it with: prog -ab -c Hello World
. 假设您的程序名为
prog
,并使用以下命令执行它: prog -ab -c Hello World
。 You want to be able to parse the arguments to say that options a
, b
and c
were specified, and Hello
and World
are the non-option arguments. 您希望能够解析参数以说指定了选项
a
, b
和c
,而Hello
和World
是非选项参数。
argv
is of type char **
—remember that an array parameter in a function is the same as a pointer. argv
类型为char **
记住,函数中的数组参数与指针相同。 At program invocation, things look like this: 在程序调用时,情况如下:
+---+ +---+---+---+---+---+
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
+---+
Here, argc
is 5, and argv[argc]
is NULL
. 在这里,
argc
为5,而argv[argc]
为NULL
。 At the beginning, argv[0]
is a char *
containing the string "prog"
. 在开头,
argv[0]
是一个char *
包含字符串"prog"
。
In (*++argv)[0]
, because of the parentheses, argv
is incremented first, and then dereferenced. 在
(*++argv)[0]
,由于括号的原因, argv
首先递增,然后取消引用。 The effect of the increment is to move that argv ---------->
arrow "one block down", to point to the 1
. 增量的作用是将
argv ---------->
箭头“向下移动一格”,指向1
。 The effect of dereferencing is to get a pointer to the first commandline argument, -ab
. 解引用的作用是获得指向第一个命令行参数
-ab
的指针。 Finally, we take the first character ( [0]
in (*++argv)[0]
) of this string, and test it to see if it is '-'
, because that denotes the start of an option. 最后,我们取(第一个字符
[0]
中(*++argv)[0]
此字符串的,并对其进行测试,看它是否是'-'
,因为这表示选项的开始。
For the second construct, we actually want to walk down the string pointed to by the current argv[0]
pointer. 对于第二种构造,我们实际上想遍历当前
argv[0]
指针所指向的字符串。 So, we need to treat argv[0]
as a pointer, ignore its first character (that is '-'
as we just tested), and look at the other characters: 因此,我们需要将
argv[0]
视为指针,忽略其第一个字符(如我们刚刚测试的'-'
),然后查看其他字符:
++(argv[0])
will increment argv[0]
, to get a pointer to the first non- -
character, and dereferencing it will give us the value of that character. ++(argv[0])
将使argv[0]
递增,以获得指向第一个非-
字符的指针,对其取消引用将为我们提供该字符的值。 So we get *++(argv[0])
. 这样我们得到
*++(argv[0])
。 But since in C, []
binds more tightly than ++
, we can actually get rid of the parentheses and get our expression as *++argv[0]
. 但是,由于在C中,
[]
比++
绑定更紧密,因此我们实际上可以摆脱括号,并将表达式表示为*++argv[0]
。 We want to continue processing this character until it's 0
(the last character box in each of the rows in the above picture). 我们要继续处理此字符,直到它为
0
(上图中每行的最后一个字符框)为止。
The expression 表达方式
c = *++argv[0]
assigns to c
the value of the current option, and has the value c
. 为
c
分配当前选项的值 ,并且值为c
。 while(c)
is a shorthand for while(c != 0)
, so the while(c = *++argv[0])
line is basically assigning the value of the current option to c
and testing it to see if we have reached the end of the current command-line argument. while(c)
是while(c != 0)
的简写,因此while(c = *++argv[0])
行基本上是将当前选项的值分配给c
并对其进行测试以查看是否有到达当前命令行参数的末尾。
At the end of this loop, argv will point to the first non-option argument: 在此循环结束时,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
+---+
Does this help? 这有帮助吗?
yes, you are correct. 是的,你是对的。
while(--argc > 0 && (*++argv)[0] == '-')
is scanning the array (of length argc) of command line arguments one by one looking for those starting with a -
option prefix. 正在扫描(长度的argc的)命令行参数逐一阵列寻找那些开始与
-
选项前缀。 For each of those: 对于每个:
while(c = *++argv[0])
is scanning through the set of switch characters that follow the first -
in the current argument (ie t
and n
in -tn
, until it hits the string null terminator \\0
, which terminates the while loop, since it evaluates as false. 正在扫描当前参数中第一个
-
后面的开关字符集(即-tn
t
和n
),直到它到达字符串null终止符\\0
为止,该字符串终止while循环,因为它的值为false。
This design allows both 这种设计允许
myApp -t -n
and 和
myApp -tn
to both work and be understood as having the options t
and n
. 既起作用又被理解为具有选项
t
和n
。
Incrementing argv is a very bad idea, as once you have done so it is difficult to get the original value back. 递增argv是一个非常糟糕的主意,因为一旦完成,就很难找回原始值。 It is simpler, clearer and better to use an integer index - after all argv IS an array!
使用整数索引更简单,更清晰,更好-毕竟argv是一个数组!
To answer your question ++argv increments the pointer. 要回答您的问题,++ argv会增加指针。 This then has indirection applied to it to get the first character.
然后对它应用了间接获取第一个字符。
The parentheses change the order in which the expressions are evaluated. 括号会更改表达式的计算顺序。
Without parentheses *++argv[0]
: 没有括号
*++argv[0]
:
argv[0]
gets the pointer to character data currently pointed to by argv
. argv[0]
获取指向argv
当前指向的字符数据的指针。 ++
increments that pointer to the next character in the character array. ++
将该指针增加到字符数组中的下一个字符。 *
gets the character. *
获取角色。 with parentheses (*++argv)[0]
: 带括号
(*++argv)[0]
:
++argv
increments the argv pointer to point to the next argument. ++argv
将argv指针递增以指向下一个参数。 *
defereferences it to obtain a pointer to the character data. *
取消引用它以获得指向字符数据的指针。 [0]
gets the first character in the character array. [0]
获取字符数组中的第一个字符。 Yes, the two expressions differ (though only slightly). 是的,这两个表达式有所不同(尽管只有一点点)。 IMO, this code is a bit on the excessively clever side.
IMO,此代码有点过于聪明。 You'd be better off with something like this:
最好使用以下方法:
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':
// ...
This is pretty much equivalent to the code above, but I doubt anybody (who knows C at all) would have any difficulty figuring out what it really does. 这几乎等同于上面的代码,但是我怀疑任何人(完全了解C)是否会真正了解它的实际作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.