1

For the following code:

char* fcn(char **para){

}

int main(void){
  char *arg[] = {"XX", "YY", "ZZ"};
  char *s = fcn(arg); 
}

Why is it that when we pass the argument into the function in char *s = fcn(arg);, we don't need to do &arg? arg[] seems to me a single pointer, so shouldn't we do &ptr for it to be referenced by a double pointer as in the parameter of fcn(): char* fcn(char **para)?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Claire
  • 167
  • 4
  • What does the function do?! It even returns nothing though its return type is not void. – Vlad from Moscow Apr 30 '21 at 15:46
  • Sorry, it does something, but I removed everything else just so that I can highlight my point better. It should just return a string of type `char *`. – Claire Apr 30 '21 at 15:52
  • Does this answer your question? [Passing a pointer to a char array as an argument to a function - C](https://stackoverflow.com/questions/28032885/passing-a-pointer-to-a-char-array-as-an-argument-to-a-function-c) – cigien May 02 '21 at 04:26

2 Answers2

1

An array when used in most expressions decays into a pointer to the first element of the array.

arg is declared as an array of char *, so a pointer to an element of the array has type char **.

If you were to use &arg, that is one of the few times an array does not decay and the expression would have type char *(*)[3], i.e. a pointer to an array of 3 elements of type char *. This is very different from char **.

dbush
  • 205,898
  • 23
  • 218
  • 273
1

If you have an array then used in expressions it is implicitly converted (with rare exceptions) to a pointer to its first element.

On the other hand, a function parameter having an array type is adjusted by the compiler to pointer to the array element type.

For example if you declared a function like

char* fcn( char *para[] );

then the compiler will adjust the function declaration the following way

char* fcn( char **para );

You even may include the both declarations in your program though the compiler can issue a message that there are redundant declarations.

So if you have a function like this

char* fcn( char *para[] );

and in the caller you have an array like this

char *arg[] = {"XX", "YY", "ZZ"};

then the function parameter and the array declared in the caller have array types with the same element type. So you may call the function like

fcn( arg );

The array used as the argument is implicitly converted to a pointer to its first element.

The type of array elements is char *. So a pointer to an element of the array will have the type char **.

That is this function call

fcn( arg );

is equivalent to

fcn( &arg[0] );

Dereferencing the pointer you will get the first element of the array having the type char *.

If you will write the expression

&arg

then the type of the expression will be char * ( * )[3]. Dereferencing the pointer you will get the original array of the type char *[3].

Here is a demonstrative program

#include <stdio.h>

void f( char **arg )
{
    printf( "sizeof( *arg ) = %zu\n", sizeof( *arg ) );
}

void g( char * ( *arg )[3] )
{
    printf( "sizeof( *arg ) = %zu\n", sizeof( *arg ) );
}

int main(void) 
{
    char * arg[] = { "XX", "YY", "ZZ" };
    
    f( arg );
    g( &arg );
    
    return 0;
}

The program output is

sizeof( *arg ) = 8
sizeof( *arg ) = 24
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335