Home > Mobile >  Why does accessing an array of pointers de-references the pointer of the pointer?
Why does accessing an array of pointers de-references the pointer of the pointer?

Time:10-26

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

  • Related