Difference between (*++argv)[0] and while(c = *++argv[0])

后端 未结 5 2045
后悔当初
后悔当初 2020-12-09 18:33

I have the following snippet of code:

int main(int argc, char *argv[])
{   

     char line[MAXLINE];
     long lineno = 0;
     int c, except = 0, number =          


        
5条回答
  •  我在风中等你
    2020-12-09 19:25

    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?

提交回复
热议问题