Difference between (*++argv)[0] and while(c = *++argv[0])
argv, c, pointers, string
Solution
First, K&R have an errata on this particular snippet:
117(§5.10): In the find example, the program increments `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`. 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.
`argv` is of type `char **`—remember that an array parameter in a function is the same as a pointer. 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`. At the beginning, `argv[0]` is a `char *` containing the string `"prog"`.
In `(*++argv)[0]`, because of the parentheses, `argv` is incremented first, and then dereferenced. The effect of the increment is to move that `argv ---------->` arrow "one block down", to point to the `1`. The effect of dereferencing is to get a pointer to the first commandline argument, `-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.
For the second construct, we actually want to walk down the string pointed to by the current `argv[0]` pointer. 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])` will increment `argv[0]`, to get a pointer to the first non- `-` character, and dereferencing it will give us the value of that character. So we get `*++(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]`. We want to continue processing this character until it's `0` (the last character box in each of the rows in the above picture).
The expression
c = *++argv[0]
assigns to `c` the value of the current option, and has the value `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.
At the end of this loop, argv will point to the first non-option argument:
+---+ +---+---+---+---+---+
| 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?
Problem
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? 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?