expected 'double **' but argument is of type 'double (*)[2]'

For starters according to the C Standard the function main without parameters shall be declared like

int main( void )

To output objects of type double you should use at least the conversion specifier %f instead of %d. Otherwise the function printf has undefined behavior.

Now about pointers.

If you have an object of type T where T is some type specifier sequence as for example

T x;

then a pointer to the object will have type T *

So let's write your program using this abstract type T.

#include <stdio.h>

void set1( T *x )
{
    //...
}


int main(void) 
{
    T x;

    set1( &x ) ;

    // ...

    return 0;
}

The program will not compile because the type T till now is unknown. But what is the type T for the original program?

It can be defined the following way

typedef double T[2];

Now if to add this typedef to the program then it will compile.

#include <stdio.h>

typedef double T[2];

void set1( T *x )
{
    //...
}


int main(void) 
{
    T x;

    set1( &x ) ;

    // ...

    return 0;
}

So what is the type of the function parameter if to use the expression &x as its argument?

Its type is double ( *x )[2]. It is not the same as double ** and there is no implicit conversion between these two types of pointers. That is pointers of these types are incompatible.

Returning to your original program in this case it will look like

#include <stdio.h>

void set1( double ( *x )[2] )
{
    (*x)[0] = (*x)[1] = 1.0;
}


int main(void) 
{
    double x[2];

    set1( &x ) ;

    printf( "%f\n%f\n", x[0] , x[1] );

    return 0;
}

If you want that the function parameter indeed had type double ** then the function argument has to be specified as it is shown in the program below

#include <stdio.h>

void set1( double **x )
{
    (*x)[0] = (*x)[1] = 1.0;
}


int main(void) 
{
    double x[2];
    double *p = x;

    set1( &p ) ;

    printf( "%f\n%f\n", x[0] , x[1] );

    return 0;
}

In this program the pointer p of the type double * points to the first element of the array and the address of the pointer of the type double ** is passed to the function.

However to change the elements of the array it is enough to declare the parameter as having the type double * because in this case the elements of the array are already passed indirectly by using a pointer.

#include <stdio.h>

void set1( double *x )
{
    x[0] = x[1] = 1.0;
}

int main(void) 
{
    double x[2];

    set1( x ) ;

    printf( "%f\n%f\n", x[0] , x[1] );

    return 0;
}

Instead of sending &x you should only send x in the function. x indicates the address of the first data in the array, and hence the starting address of the array itself. What you should do is:

void set1(double *x)
{
    x[0] = x[1] =1.0;
}

int main()
{
    double x[2];
    set1(x);
    printf("%d\n%d\n",x[0],x[1]);
}

You're problem arises because you set the type of the argument as a pointer to a pointer to a double value but sent a pointer to an array of double values of length 2 instead.

Tags:

C

Arrays

Pointers