2

At first I would guess that the values of k1 won't be in the main space. But then I realized that an array is a pointer, so is there any difference? I think that is the same, but maybe anyone can find some other technical differences. Maybe is faster passing a pointer?

#include <iostream>

using namespace std;

void g(double [],int );
void f(double* [],int );

int main()
{

    int n = 10;
    double *k1, *k2;

    k1 = new double[n];
    k2 = new double[n];

    g(k1,n);
    f(&k2,n);

    for(int i = 0;i <n;i++)
    {
        cout << k1[i]<< " ";
        cout << k2[i] << endl;
    }

    delete [] k1;
    delete [] k2;

    return 0;
}


void g(double h[],int n)
{
     for(int i = 0;i <n;i++)
        h[i]=i;
}

void f(double* h[],int n)
{
     for(int i = 0;i <n;i++)
        (*h)[i]=i;
}
Pablo Riera
  • 349
  • 3
  • 15
  • 1
    An array is different from a pointer, but a function parameter declared as an array actually IS a pointer. – Ben Voigt Jul 26 '13 at 19:56
  • @Nikos: He's passing the address of a `double*`, not a `double*`. – Ben Voigt Jul 26 '13 at 19:59
  • Actually it takes neither a pointer to a double nor a pointer to a pointer to a double. It takes a pointer to an array which is different. – Dale Wilson Jul 26 '13 at 20:00
  • @BenVoigt Oops, indeed. – Nikos C. Jul 26 '13 at 20:00
  • 3
    @DaleWilson The `[]` notation in function arguments is just syntactic sugar for a pointer. It's not an array. These two arguments are both pointers to an `int`: `int* a` and `int a[]`. – Nikos C. Jul 26 '13 at 20:02

6 Answers6

11

First of all, arrays are not pointers. This is an array of 10 doubles:

double a[10];

This is a pointer to double:

double *p;

This is a pointer to an array of 10 doubles:

double (*pa)[10];

And this is an array of pointers to doubles:

double *pa[10];

Arrays and pointers are only the same when declared as function arguments. But arrays can be converted (decay) into pointers to the first elemento of the array:

double a[10];
double *p = a;
double *q = &a[0]; //same as p

In your sample code:

double *x = new double[10];

You are creating a dynamic array of 10 doubles and getting a pointer to the first element of that array. You could also create a new array and get a pointer-to-array:

double (*x)[10] = new double (*)[10];

But this show of weird syntax is seldom useful.

About functions, this is a function taking an array of doubles:

void g1(double h[], int n);

And this is a function taking a pointer to an array of 10 doubles:

void g2(double (*h)[10]);

In the pointer-to-array case you need to specify the size of the array, because you cannot create a pointer to an unknown-size array.

That's why arrays are actually passed to functions as pointers. But pointers to the first member of the array, not pointers to the array itself. So the first function is actually identical to this one:

void g1(double *h, int n);

Since you only pass the pointer to the first member of the array (pointer to double) you need also to specify the size of the array, in an additional paramenter. The advantage is that you can pass arrays of any size. And even splices of an array:

double x[20];
g1(x + 10, 5); //pass x[10..15]

About which one is faster, they are both the same, they are actually pointers to the same memory address. Note that arrays are only passed by copy if they are part of a struct, and the struct is passed by value.

My recommendation is: if you use C stick to the idiomatic C, use pointers to the first member of the array when necessary, and avoid the pointer-to-array syntax when possible. If you use C++ use containers, iterators and ranges.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
3
void f(double* h[],int n)

is not accepting a pointer to an array. You've declared it to accept an array of pointers.

The only reason it works is that function parameters declared as arrays are silently turned into pointers, and so it is equivalent to:

void f(double** h,int n)

which is what you wanted after all.

This (rejected by g++) code would use a pointer to an array:

void f(double (*h)[],int n)
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

With this declaration:

void f(double* [],int );

You are saying that, as first parameter, you are taking an array of pointers to double.

When you dereference that parameter (which is treated like a pointer to pointer) with (*h), you actually get the address of the first location of the array.

Vincenzo Pii
  • 18,961
  • 8
  • 39
  • 49
1
void g(double h[],int n);

In that function you are technically passing a pointer.

void f(double* h[],int n);

However in this one, you are passing a pointer to an array, which resolves to a pointer to pointer as it is a function parameter*.

*Credit to Ben Voigt

Joseph Pla
  • 1,600
  • 1
  • 10
  • 21
  • 2
    No, that's an array of pointers. Sort of. It turns out to be a pointer to pointer to double, since that's how arrays are passed, so things *work* but very much by accident. – Ben Voigt Jul 26 '13 at 20:00
  • At the risk of getting flamed, most times, an array is "essentially" a pointer. To the typical user, anyway. – Jiminion Jul 26 '13 at 20:01
  • The binary value is the same as a pointer to a pointer to a double, but the code generated by the compiler to use that value will be different (and painfully wrong unless you really know why you want a pointer to an array. – Dale Wilson Jul 26 '13 at 20:02
  • an array is a pointer with a name to abstract the user from what it really is. When it comes down to it, thats what it is. – Joseph Pla Jul 26 '13 at 20:03
  • 1
    @Joseph: No it isn't. An array object has an implicit conversion to a pointer, but an array is not a pointer. In cases like `sizeof` or template type inference, that conversion won't be used. (And add the confusion that array syntax in a function parameter declaration actually gives you a pointer and not an array after all). – Ben Voigt Jul 26 '13 at 20:04
  • @benVoight Alright, fair enough. But am I wrong in saying that once declared, its use is syntactically the same? – Joseph Pla Jul 26 '13 at 20:07
  • @BenVoight I'm not quite understanding. What I'm saying is that, like you point out in your answer, it is silently converted to a pointer. Anyways, my bad, and I guess this has no place in comments anyways :P – Joseph Pla Jul 26 '13 at 20:07
  • 1
    @Joseph: For function parameters yes, because function parameters can't be arrays (see Nikos's "syntactic sugar" comment on the question). For actual array objects, they're like pointers insofar as pointer arithmetic and subscripting work. But they're unlike pointers in context which does type inference (`decltype`, `sizeof`, and templates). – Ben Voigt Jul 26 '13 at 20:09
  • Isn't this the old char **argv vs. char *argv[] argument? Essentially the array gets decayed to a pointer type and one would just use the array version of the argument to a function just to specify the argument meaning showing in this case this is an array of char*. Shoot my double star got converted to italics... how can i fix that in a comment? – bjackfly Jul 26 '13 at 20:09
  • Looks like I need to do some more reading... thanks guys. – Joseph Pla Jul 26 '13 at 20:11
  • @bjackfly: Use backticks ```` to surround code snippets, it prevents formatting. – Ben Voigt Jul 26 '13 at 22:50
1

Even though you passed the pointer by-value, the memory that it is pointing to can still be changed by a function.

Jiminion
  • 5,080
  • 1
  • 31
  • 54
0

Many programmers have a mental model of how the compiler works that includes "an array is just a pointer". This model is incorrect.

 typedef int[10] Array;
 typedef Array * PointerToArray;
 typedef int * Pointer;

 Array a = {0,1,2,3,4,5,6,7,8,9};
 PointerToArray pa;
 Pointer pint = a;   // the compiler casts this automatically to a different type.

At this point pint and pa have the same binary value, but pa[1] and a[1] do NOT reference the same location in memory. It is important to understand why.

Dale Wilson
  • 9,166
  • 3
  • 34
  • 52