4
int main(){
    int a[10][10];
    int **ptr =(int **)a;
    cout<<a<<endl<<ptr<<endl;
    cout<<*a<<endl<<*ptr<<endl;
    return 0;
}

Output of this code on my computer is

0021FC20
0021FC20
0021FC20
CCCCCCCC

Why is "a" equal to "*a"? why isn't *a equal to *ptr?

Ganesh
  • 57
  • 8
  • 7
    `int **ptr =(int **)a;` is an illegal cast. There is no conversion from nested arrays to nested pointers. See our [related FAQ](http://stackoverflow.com/questions/4810664/). – fredoverflow Mar 06 '12 at 11:55
  • 7
    Don't use `(cast)` syntax. If you [used the proper `static_cast` syntax](http://ideone.com/89Zml), you would have been told immediately by your compiler that the cast is not valid. – R. Martinho Fernandes Mar 06 '12 at 11:59

5 Answers5

4

Why is a equal to *a?

When used in a context that requires a pointer, an array will be converted to a pointer to its first element. a is an array of arrays; so it will decay to a pointer to the first array. *a is the first array, and will decay to a pointer to the first integer in that array. Both of these exist at the same location, so the two pointers will have equal values.

why isn't *a equal to *ptr?

Because the conversion from an array of arrays, to a pointer-to-pointer, is not valid. You have forced the conversion using a cast - the dangerous C-style cast, which in this case acts like reinterpret_cast - so *ptr will read the first few bytes of the array and interpret that as a pointer (probably - the behaviour here is undefined, so in principle anything could happen). There is no pointer in the memory pointed to by ptr, so *ptr will certainly not give you a valid pointer.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

Why is a equal to *a?

Since you cannot print an array, a is implicitly converted from int[10][10] to int(*)[10]. So what actually gets printed instead of a is a pointer to the first line of a.

*a is the first line of the array, and that in turn gets converted to a pointer to the first element.

Since an array has the same address as its first element, you get the same value twice.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
1

A 2D C array is NOT a pointer to a pointer. IT is effectively a pointer with rows * columns elements in it.

int main(){
    int a[10][10];
    int *ptr =(int *)a;
    cout<<a<<endl<<ptr<<endl;
    cout<<*a<<endl<<*ptr<<endl;
    return 0;
}

The above will give you what you are after.

Although when you de-reference a or ptr you will find you get an "undefined value"

if you set a[4][4] to say 5

Then you will find the value stored at

ptr[(row * 10) + column) will return that value where row = 4 and column = 4.

Goz
  • 61,365
  • 24
  • 124
  • 204
1

I then would suggest to avoid static stack allocation of big matrices, choose dynamic allocation (on the heap) instead...

linello
  • 8,451
  • 18
  • 63
  • 109
1

The mechanics of 2D arrays are actually easier than they first appear but it's usually poorly taught. Nevertheless, it does take a lot of experience to quickly decipher things and even experienced developers sometimes have to stop and think for a moment (or two). Basically, when you see a 2D array such as int a[5][10] (I'm changing the size of your array to 5 to simplify things), you need to stop thinking about it as 2D. Think of it as 1D instead. The first subscript specifies the number of elements in this 1D array, just like any other 1D array. When you index into the array, such as a[3], you're therefore accessing the object at index 3. This is no different than any other array. Let's say "a" was defined like this instead:

// Note: The size of the array, 5, can be omitted
int a[5] = {5, 10, 15, 20, 25};

Subscripting then yields this:

a[0] = 5
a[1] = 10
a[2] = 15
a[3] = 20
a[4] = 25

That's easy enough and most get it. But if you now do this:

// Note: Like above, the size of the array, 5, can be omitted
int a[5][10] = {{  5,  10,  15,  20,  25,  30,  35,  40,  45,  50},
                { 55,  60,  65,  70,  75,  80,  85,  90,  95, 100},
                {105, 110, 115, 120, 125, 130, 135, 140, 145, 150},
                {155, 160, 165, 170, 175, 180, 185, 190, 195, 200},
                {205, 210, 220, 225, 230, 235, 240, 245, 250, 255}};
          

You still have a 1D array of 5 elements, and you can subscript into it just like the previous example, yielding the following (not real syntax, just how you should think about it):

a[0] =   5  10  15  20  25  30  35  40  45  50
a[1] =  55  60  65  70  75  80  85  90  95 100
a[2] = 105 110 115 120 125 130 135 140 145 150
a[3] = 155 160 165 170 175 180 185 190 195 200
a[4] = 205 210 220 225 230 235 240 245 250 255

The only difference here is that instead of each element being an "int" like the previous example, each element is an array instead (of 10 integers). Therefore, when you subscript into it as seen, each index (0 to 4) returns the array of 10 integers for that row. For instance, a[3] returns the array of 10 integers containing the values 155 to 200. The element itself is an "int[10]" and you can therefore treat it that way. IOW, you're getting back the equivalent of this:

int b[10] = {155, 160, 165, 170, 175, 180, 185, 190, 195, 200};

And so, for example, in the same way that b[7] = 190, a[3][7] = 190 as well, since a[3] is effectively returning the equivalent of b (an array of 10 integers), and the [7] subscript then grabs the element at index 7 of that array, just like b[7]. Moreover, in the same way that b is a pointer to the first element of the array (since all array names decay into a pointer to the first element of the array), which in this case is 155 (i.e., "b" decays to an int * pointing at 155), a[3] returns (decays into) the same thing. Why? Because it's returning the equivalent of b as described, and just like b, it decays into a pointer to its first element. IOW, just like this is true:

int *p = b; // "b" decays into a pointer to its first element (an "int")
int val = *p; // Equals 155

This is also true:

int *p = a[3]; // a[3] returns the equivalent of "b", an int[10], and this decays into a pointer to its first element, just like "b"
int val = *p; // Equals 155

And finally, just like FredOverflow mentioned, this is also true:

int (*p)[10] = a;

The syntax takes getting used to but it makes perfect sense. Since every array name decays into a pointer to its first element as discussed, "a" therefore decays into a pointer to its first element. What is that element? Well, each element of "a" is an array of 10 integers, i.e., an "int[10]", so "a" must decay into a pointer to the first of these "int[10]" elements. The syntax just above is how you declare this pointer. It defines "p" as a pointer to an array of 10 integers. The (circular) brackets are required because of the C++ precedence rules. If you removed them you would get this:

int *p[10] = a; // Compiler error!

Which declares "p" as an array of 10 elements, where each element is a pointer to an int. It's not the same IOW so the brackets are required to change the precedence (and hence the meaning of this declaration). Using the proper syntax previously shown, "p" would therefore point to the first element (the "int[10]" array containing the elements 5 to 50), p + 1 would point to the second element (the "int[10]" array containing the elements 55 to 100), etc. Bonus points: What would the following therefore do?

(*(p + 3))[5]

It returns 180 because (p + 3) returns a pointer to the array of 10 integers at "a[3]" and when dereferenced using the * operator, you get the actual "int[10]" array at this location. The [5] subscript then yields the value 180 in this array.

No doubt it will still take a lot of practice to get your head around this but I hope that helps.

Larry
  • 796
  • 6
  • 13