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?
The first parameter, argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started. The second parameter, argv (argument vector), is an array of pointers to arrays of character objects.
By convention, argv[0] is the command with which the program is invoked. argv[1] is the first command-line argument. The last argument from the command line is argv[argc - 1] , and argv[argc] is always NULL.
The variable argv points to the start of an array of pointers. argv[0] is the first pointer. It points at the program name (or, if the system cannot determine the program name, then the string for argv[0] will be an empty string; argv[0][0] == '\0' ).
They are used to control program from outside instead of hard coding those values inside the code. argv[argc] is a NULL pointer. argv[0] holds the name of the program. argv[1] points to the first command line argument and argv[n] points last argument.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With