3

Possible Duplicate:
How do I use arrays in C++?
Is 2d array a double pointer?
Two dimensional arrays and pointers

I know that this is a very basic question but no amount of googling cleared this for me. That's why am posting it here. In c++ consider the declaration int x[10];

This is a 1-dimensional array with x being the base pointer that is it contains the address of the first element of the array. So x gives me that address and *x gives the first element.

similarly for the declaration

 int x[10][20];

what kind of variable is x here. When i do

 int **z = x;

the compiler says it cannot convert int (*)[20] to int **.And why does cout<<x; and cout<<*x; give the same value?? And also if i declare an array of pointers as

 int *p[10];

then is there a difference between x and p ( in their types) ?? because when one declares int x[10] and int *p then it is valid to assign x to p but it is not so in case of two dimensional arrays? why? Could someone please clear this for me or else provide a good resource material on this.

Community
  • 1
  • 1
newbie
  • 281
  • 4
  • 9
  • 2
    All of this can be answered by reading the [C FAQ on *Arrays and Pointers*](http://c-faq.com/aryptr/index.html). – Oliver Charlesworth Jul 16 '12 at 20:12
  • you can retrieve and element from the 2 dimensional array like this as well *(x + 20*(row) + col), so x is a multidimensional array still gives the pointer to the first value – user1084113 Jul 16 '12 at 21:10

3 Answers3

5

Arrays and pointers aren't the same thing. In C and C++, multidimensional arrays are just "arrays of arrays", no pointers involved.

int x[10][20];

Is an array of 10 arrays of 20 elements each. If you use x in a context where it will decay into a pointer to its first element, then you end up with a pointer to one of those 20-element arrays - that's your int (*)[20]. Note that such a thing is not a pointer-to-a-pointer, so the conversion is impossible.

int *p[10];

is an array of 10 pointers, so yes it's different from x.

In particular, you may be having trouble because you seem to think arrays and pointers are the same thing - your question says:

This is a 1-dimensional array with x being the base pointer that is it contains the address of the first element of the array. So x gives me that address and *x gives the first element.

Which isn't true. The 1-dimensional x is an array, it's just that in some contexts an array decays into a pointer to its first element.

Read the FAQ for everything you want to know about this subject.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • Thanks for your reply.I am a lot more clearer now than when i started..but i still don't understand how exactly does `**x` work? Here we are almost using x as if it were a pointer to a pointer pointing to the first element right? coz **x gives the value of the first element of the array. – newbie Jul 17 '12 at 06:49
  • @newbie, you can't use `**x` at all in any of your examples. – Carl Norum Jul 17 '12 at 18:39
  • `#include` `using namespace std;` `main()` `{` `int x[10][20];` `x[0][0]=11;` `cout<<**x< – newbie Jul 19 '12 at 02:02
5

Multidimensional arrays are simply syntactic sugar. Behind the scenes this is simply a one dimensional array 10 * 20 ints long. When you access an element at x[5][6] the compiler generates the equivalent to x[5 * 20 + 6];

alekop
  • 2,838
  • 2
  • 29
  • 47
  • 1
    This is true, but doesn't answer the question. – Oliver Charlesworth Jul 16 '12 at 20:25
  • @OliCharlesworth: I felt that the OP is unsure about the physical difference between one- and multi-dimensional arrays, and wanted to clarify. Since he's working directly with the array memory, it may be helpful to know how the arrays are actually laid out in memory. – alekop Jul 16 '12 at 20:48
  • it should be `x[5 * 20 + 6]` to access `x[5][6]` where x is a matrix with 10 rows and 20 columns, stored in row major. – Ritwik Jan 10 '17 at 14:46
  • @Ritwik You're right. I updated the answer. Thanks. – alekop Jan 10 '17 at 23:39
  • If it was that simple, it would work. it doesn't. – MarcusJ Jan 28 '17 at 18:43
  • Would anybody like to try this equivalence in C, `x[5][6]` would be the same as `((int*)x)[5 * 20 + 6]` (cast to 'array' of `int`) – fordcars Feb 19 '20 at 21:30
2

Here's how it really works, see the code and comments:

#include <stdio.h>

int x[3][5] =
{
  {  1,  2,  3,  4,  5 },
  {  6,  7,  8,  9, 10 },
  { 11, 12, 13, 14, 15 }
};

int (*pArr35)[3][5] = &x;
// &x is a pointer to an array of 3 arrays of 5 ints.

int (*pArr5a)[5] = x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints.

int (*pArr5b)[5] = &x[0];
// &x[0] is a pointer to 0th element of x,
// x[0] is an array of 5 ints,
// &x[0] is a pointer to an array of 5 ints.

int *pInta = x[0];
// x[0] is 0th element of x,
// x[0] is an array of 5 ints,
// x[0] decays from an array of 5 ints to
// a pointer to an int.

int *pIntb = *x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints,
// *x is an array of 5 ints,
// *x decays from an array of 5 ints to
// a pointer to an int.

int *pIntc = &x[0][0];
// x[0][0] is 0th element of x[0],
// where x[0] is an array of 5 ints,
// x[0][0] is an int,
// &x[0][0] is a pointer to an int.

int main(void)
{
  printf("&x=%p x=%p &x[0]=%p x[0]=%p *x=%p &x[0][0]=%p\n",
         pArr35, pArr5a, pArr5b, pInta, pIntb, pIntc);
  return 0;
}

Sample output:

&x=0040805c x=0040805c &x[0]=0040805c x[0]=0040805c *x=0040805c &x[0][0]=0040805c

All the resultant pointers are the same value-wise because I used explicitly or implicitly indices of 0 and because arrays are contiguous and their very first (IOW, 0th) element is always at the lowest address in the array. So, even though there are 3 different pointer types, all effectively point at x[0][0], at the element that's equal 1.

This decaying of arrays to pointers is a very important feature of C and C++, although it's hard to grasp immediately.

It lets us write more compact code when passing pointers to arrays, we can just write the array's name instead of taking the address of its first element:

char str1[] = { 's', 't', 'r', '1', '\0' };
char str2[] = "str2";
printf("%s %s %s %s\n", &str1[0], str1, &str2[0], str2);

Output:

str1 str1 str2 str2

It also lets us do crazy things:

int y[3] = { 10, 20, 30 };
printf("%d %d %d %d\n", y[2], *(y+2), *(2+y), 2[y]);

Output:

30 30 30 30

All because a[b] is equivalent to *(a+b) when it comes to arrays and pointers.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180