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