4

I have this small program:

#include <stdio.h>

int main() {
    char *argv[3] = {{"abc"}, {"def"}, {"ghi"}};

    printf("%c\n", (*++argv)[1]); //error. I wanted to print 'b'
    printf("%c\n", *++argv[1]); //prints e

    return 0;
}

The error message:

error: cannot increment value of type 'char *[3]'
printf("%c\n", (*++argv)[1]);

I want to increment argv to point to b. I took this usage (*++argv)[i] straight from C Programming Language by K&R where they have an example on page 117 on incrementing argv exactly like I did. They also point out that (*++argv)[0] is the pointer to the first character in a string while *++argv[0] increments the pointer argv[0]. Indeed (*argv)[1] will print b while *argv[1] will print d. Yet somehow incrementing (*++argv)[0] just keep resulting in error.

2
  • 1
    you have an array of pointers, not a pointer to array. and the way argv is declared could be different. I guess in k&r it declared as "char**". Commented Dec 10, 2016 at 11:56
  • 1
    it'll be helpful if you show the error message. in this case you get the error because argv is an array and you can not use ++ on it because it's value can not be changed. Commented Dec 10, 2016 at 12:01

3 Answers 3

4

First, this:

char *argv[3] = {{"abc"},{"def"},{"ghi"}};

Should be this, as noted by others:

char *argv[3] = {"abc", "def", "ghi"};

Second, what you've done is not what the K&R book does.

Array names act like they were constant pointers, so you can't change them like you tried to with that argv = argv + 1 (expanded version of ++argv).

But the book does that to an argv passed into main by the command line, so when char* argv[] enters main, it decays to a pointer to pointer (char**) and then, yes, you could make (*++argv)[1] work if you pass the strings as command line arguments.

Try to create a bogus argv inside main, like you did, and compare its related addresses with the addresses related to a real argv passed into main via command line.

You'll see that one is a char** and the other is a char* array:

#include <stdio.h>

int main(int argc, char* argv[]) 
{    
    printf("argv:     %p\n", argv);
    printf("&argv[0]: %p\n", &argv[0]);
    printf("&argv:    %p\n\n", &argv);

    char* bogus_argv[] = {"abc", "def", "ghi"};
    printf("bogus_argv:     %p\n", bogus_argv);
    printf("&bogus_argv[0]: %p\n", &bogus_argv[0]);
    printf("&bogus_argv:    %p\n\n", &bogus_argv);

    printf("%c\n", (*++argv)[1]);  // prints 'b'
    printf("%c\n", *++argv[1]);    // prints 'e'

    return 0;
}

Run: ./program abc def ghi

Output on my machine:

argv:     0x7ffcde5aca98
&argv[0]: 0x7ffcde5aca98
&argv:    0x7ffcde5ac9a0

bogus_argv:     0x7ffcde5ac980
&bogus_argv[0]: 0x7ffcde5ac980
&bogus_argv:    0x7ffcde5ac980

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

Comments

2

The example from K&R refers to argv as defined as the second argument to function main. Your definition is different, you define an array of 3 pointers to strings whereas the function argument is a pointer to such an array.

The function prototype syntax is somewhat misleading as the same syntax is used for a different type of object. Some people prefer this syntax:

int main(int argc, char **argv) {
    ...
}

With this prototype, the nature of argv (a pointer to a pointer to char) appears more explicitly, but many programmers prefer the equivalent char *argv[] syntax to underline the fact that argv points to an array of pointers as opposed to a single pointer.

argv being an array in your code, you cannot increment it: this explains why you get an error for printf("%c\n", (*++argv)[1]);.

You can change your program this way:

#include <stdio.h>

int main(void) {
    char *argument_array[4] = { "abc", "def", "ghi", NULL };
    char **argv = argument_array;

    printf("%c\n", (*++argv)[1]); // will print 'e' instead of 'b'
    printf("%c\n", *++argv[1]);   // prints 'h', not 'e'

    return 0;
}

Also note that you should remove the redundant {} in the initializer, and the ++ operator is prefix, so the output is not exactly what you expect.

Comments

1

you made a mistake with array your declaration. It should you a warning. It should be

char *argv[3] = {"abc","def","ghi"};

The inner braces are not neccessary as strings are char pointers and therefore "arrays".

You could declare a second pointer variable and assign it to argv:

char ** p;
p = argv;

and then increment p.

Last but not least, if you want to print b first and then e, you have to put the "++" operator behind the variable. Otherwise it would increment the pointer before the evaluation and you would print e and h.

5 Comments

good point with the braces. I re-declared the array still I get the same error.
what about the other things i mentioned?
creating p didn't help as well. Regarding incrementing, good point as well, but the main issue persists.
you also put p in the printf argument instead of argv.
printf("%c\n", (*p++)[1]);

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.