6 Answers
6

The code is playing evil pointer games, without luck. You are passing a pointer having type int(*)[10] to a function that wants a pointer having type int**. The pointer you pass has as value the "base address" of the array.

So, when you dereference the int**, it thinks at that address it gets an int*, even though what it looks at is an int object. And it writes the address returned from malloc into that memory cell.

Back in main, you print out that cell. Note that it is the value of the array's first element, not the address of the array's first element. So what is printed is the integer value interpretation of the address you wrote in the called function.

What you do is undefined behavior: The function wants a int**, so you have to give it an int**,

Here is how i think you view the matter

You hear someone say that an array name is a constant pointer to its first element

You take the address of that pointer, cast away any const

You happily write some other address into the pointer, and hope that it doesn't crash

You use the array again, expecting it "overlays" now the uninitialized memory region that malloc created.

But that view is flawed. The first point is flawed the most, because an array name is not a constant pointer. If the first point were correct, your snippet would make a lot more sense, actually. But an array name will generate an address value that refers to its first element when you use it in an expression, except in very few cases (sizeof, address-of).

Because that address value is not generated when you use address-of, you will get a pointer to that array instead (which was exactly what you wrote with the address-of operator). Since it makes sense that an array and the first element of it has the same address, the address of an array happens to equal to the address of its first element. So what you actually did was writing into the first element, instead of writing into some pointer (that in reality isn't there).

Response to Comment

Consider what happens when the type of the array matters in practice (out of these experiments). You have an array whose elements are arrays themselves.

// array of 3 "array of 10 int"
int a[3][10];

So, by using a in an expression other than & and sizeof, you will get a pointer to the first element, int(*)[10]. This is crucial, because the following writes into an integer that's offset 2*sizeof(int)*10 bytes

a[2][0] = 1;
// (a + 2) refers to a offset by 2*sizeof(int)*10 bytes

If a in that expression would give you an int**, then the compiler would have no idea where it should store the integer 1 correctly into, because any size information about the element type is lost. It could surely store the size somewhere in memory, but where? In the array, there is no space for that. And in addition, sizeof couldn't be able to give you a compile time result anymore.

+1 Aye. This is like stabbing the program in the back with a rusty dagger.
–
ralphtheninjaJul 11 '09 at 16:09

Wait a minute, now I'm confused. What is a if not an int*? I know that the square brackets are really just dereferencing the first address plus the value in the brackets. I thought that int a[10]; was just allocating an array of 10 ints on the stack and making a the pointer to the first one. So my question is, what is the difference between an int(*)[10] and an int**?
–
SeanJul 11 '09 at 16:18

Here *a means First value of array... not the address of array.
For cross-checking... after changeArray Function iterate over the array, you get to know it's first element that gets changing not the array adress which is const poiter....

What you are doing is using malloc system call you are requesting 4 bytes of memory and then that address will get stored in first array element....