1

I am reading a linux programming with c language book and it has the following code.

        int main(int argc, char *argv[])
    {
        int opt;
        while ((opt = getopt(argc, argv, "iv")) != -1) {
            switch (opt) {
            case 'i':
                opt_ignorecase = 1;
                break;
            case 'v':
                opt_invert = 1;
                break;
            case '?':
                fprintf(stderr, "Usage: %s [-iv] [<file>...]\n", argv[0]);
                exit(1);
            }
        }
        argc -= optind;
        argv += optind;
}

I don't understand that why argv += optind works. When i tried at another program, which is the following:

int main(int argc, char* argv[])
{
    
    char* test[] = {"Hello", "World", "I"};
    argv += 1;
    test += 1;
    printf("%s", test[0]);
    return 0;
}

the gcc compiler shows error

a.c:8:9: error: assignment to expression with array type
8 |    test += 1;

the += on argv works but doesn't work with test. I don't understand which part I did wrong..

1
  • 2
    char* argv[] as a function parameter is a different way to write char** argv. So, it is a pointer to a pointer, test is an array of pointer Commented Nov 17, 2020 at 14:35

2 Answers 2

3

When an array declaration appears in a function parameter list, it is automatically adjusted to declare a pointer. So int main(int argc, char *argv[]) actually declares argv to have type char **.

Since argv is a pointer, we can increment it with argv += optind;. argv initially points to the first of several char *, and argv += optind; changes which of those char * it points to.

In contrast, the declaration char* test[] = {"Hello", "World", "I"}; defines test to be an array of char *. Since it is an array, it cannot be moved; test += 1 attempts to change where the array is, and that is not allowed.

After defining test, you could define a new pointer, char **p = test;, and then you could adjust p with p += 1;. (Note that in char **p = test;, test is automatically converted to a pointer to its first element, so this is equivalent to char **p = &test[0];.)

(Note: Grammatically, the * in char * test [] binds with test [], not char, so char* test[] is misleading. A declaration such as char* a, b; would not declare both a and b to be char*. It declares a to be char * and b to be char, so char *a, b; is a better picture of the meaning.)

Sign up to request clarification or add additional context in comments.

2 Comments

Hi eric, thank you for your explanation. After trying to do something like char *hello[] = {"Hello", "I", "am", "Low"}; char ** test = hello; it works. By the way, a little out of topic, whats the downside if i do something like above?
@nicklowkc: There is not much downside by itself, and I would not worry about it until you are further along in learning C and programming. One downside is that form requires two identifiers, hello and test, whereas it can be done with one, char **test = (char *[]) {"Hello", "I", "am", "Low"};. But there are other considerations in the context of a program, such as whether the array should be static or automatic, whether you need to reset to the beginning, whether the same strings are used elsewhere, and so on.
1

argv doesn't have array type, despite how the declaration is written; its actual type is char **.

In a function parameter list, any declaration of the form T a[N] or T a[] is adjusted to T *a - all three declare a as a pointer, not an array. This is only true for function parameter declarations, not regular declarations.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.