3

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;
}
5
  • 1
    An array is different from a pointer, but a function parameter declared as an array actually IS a pointer. Commented Jul 26, 2013 at 19:56
  • @Nikos: He's passing the address of a double*, not a double*. Commented Jul 26, 2013 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. Commented Jul 26, 2013 at 20:00
  • @BenVoigt Oops, indeed. Commented Jul 26, 2013 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[]. Commented Jul 26, 2013 at 20:02

6 Answers 6

12

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.

Sign up to request clarification or add additional context in comments.

Comments

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)

7 Comments

There is nothing illegal about that declaration.
@Carl: Isn't there? g++ gives "error: parameter ‘h’ includes pointer to array of unknown bound ‘double []’"
Hmm - clang took it silently. Compiler extension? Let me try GCC.
GCC complained to me as you say; I wonder why clang took that...
@Carl: It makes sense that it should be allowed, since you can form a pointer to an incomplete type. You can't do pointer arithmetic (including subscripting) with it, but that's an entirely different issue.
|
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.

Comments

1

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

Comments

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

11 Comments

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.
At the risk of getting flamed, most times, an array is "essentially" a pointer. To the typical user, anyway.
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.
@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).
@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).
|
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.

1 Comment

pa doesn't have any value, it is uninitialized...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.