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.
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
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.
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