I cannot understand this unexpected C behavior where printing argv[0]
prints ./a.out
instead of the actual content of argv[0]
which should be a memory address because argv
is an array of pointers.
If I create an array called char name[] = "hello"
then I would expect to see h
at name[0]
and if char * argv[]
holds, for example 3 pointers (memory addresses) then logically argv[0]
should be a memory address.
My reasoning is that if I wanted to access the actual content of the memory address that argv[0]
points to I should need to do *(argv[0])
. What is happening here? Is C doing some kind of magic here?
------ ------ ------ --- --- ----
| h | e | l | l | o | \0 |
------ ------ ------ --- --- ----
^---- name[0] = h
------ ------ ------
| 0xA7 | 0xCE | 0xC4 |
------ ------ ------
^---- argv[0] = should be 0XA7 (the value of `argv[0]`,
not the value it points to
#include <stdio.h>
int main(int argc, char * argv[]) {
char name[] = "hello";
printf("%c \n", name[0]); // expected h
printf("%s \n", argv[0]); // expected 0xA7 (but got ./a.out instead)
}
$ gcc main.c
$ ./a.out arg1 arg2 arg3
CodePudding user response:
My reasoning is that if I wanted to access the actual content of the memory address that argv[0] points to I should need to do *(argv[0]). What is happening here?
printf
is doing the dereferencing. printf( "%s", argv[0] )
tells uses printf
to print *(argv[0])
, *(argv[0] 1)
, *(argv[0] 2)
, etc until a NUL (zero) is encountered.
printf
could not be written to accept *(argv[0])
. That would simply pass .
instead of an address, so printf
would be unable to determine which character came next.
CodePudding user response:
For an array declared like
char name[] = "hello";
the expression name[0]
has the type char
and by using the conversion specifier c
in the call of printf
printf("%c \n", name[0]);
the first element of the array is outputted as a character.
This declaration of an array
char * argv[]
that is used as a parameter declaration is adjusted by the compiler to the declaration
char **argv
and the expression argv[0]
has type char *
.
The conversion specifier s
is designed to output strings pointed to by corresponding arguments like this
printf("%s \n", argv[0]);
argv[0]
points to a string that contains the name of the program that runs.
If you want to output the expression as an address you need to write
printf("%p \n", ( void * )argv[0]);
To make it more clear consider this statement
printf( "%s\n", "Hello" );
Its output as I think you are expecting is
Hello
The string literal has the type char[6]
. But using as an expression in the call of printf it is implicitly converted to pointer to its first element of the type char *
.
So the second argument of the call of printf has the type char *
the same way as in the call
printf("%s \n", argv[0]);
where teh second expression also has the type char *
.