0

The following code,according to me should run successfully,but fails at runtime.I don't get the reason:

 void main()
 {
   int arr[5][3]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
   int *m=arr[0];
   int **p=&m;
   p=p+1;
   printf("%d",**p);

  }

a.exe has stopped working at runtime in gcc compiler,windows 7 64 bit

user1369975
  • 430
  • 1
  • 6
  • 19

4 Answers4

8

An array of arrays and a pointer to a pointer is quite different, and can't be used interchangeably.

For example, if you look at your array arr it looks like this in memory

+-----------+-----------+-----------+-----------+-----+-----------+
| arr[0][0] | arr[0][1] | arr[0][2] | arr[1][0] | ... | arr[4][2] |
+-----------+-----------+-----------+-----------+-----+-----------+

When you have the pointer-to-pointer p the program don't really knows that it points to an array of arrays, instead it's treated as an array of pointers, which looks like this in memory:

+------+------+------+-----+
| p[0] | p[1] | p[2] | ... |
+------+------+------+-----+
  |      |      |
  |      |      v
  |      |      something
  |      v
  |      something
  v
  something

So when you do p + 1 you get to p[1] which is clearly not the same as arr[1].

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Nice answer, from ascii-flow **?** – Grijesh Chauhan Jul 23 '13 at 11:19
  • 2
    @GrijeshChauhan Ha ha, nope, still doing it by hand :) – Some programmer dude Jul 23 '13 at 11:21
  • he also need to answer preferable way to declare and initialized 2d-matrix. I think so. – Grijesh Chauhan Jul 23 '13 at 11:22
  • 1
    +1 I also want to draw pictures like these (while answering of course), though it looks impossible for me to draw with hand ...... are there any tools used for this ?? – 0decimal0 Jul 23 '13 at 11:27
  • @JoachimPileborg,nice answer,thanks,but still don't get why to int** p=&arr[0] and p=p+1 will not point to arr[1].I thought 4 should be printed as arr[1] will point to arr[1][0].Why I am going wrong? – user1369975 Jul 23 '13 at 12:21
  • @user1369975 When you have an array `arr`, and to `arr + 1` it's the same as `arr[1]`. However `p` *isn't* an array even though it can be treated as one. And when you treat it as an array it's not an array of arrays, but an array of pointers. So while `p` may point to `arr[0][0]` it's treated completely differently. Also, doing `arr + 1` adds `sizeof(int[3])` bytes to `arr`, but `p + 1` adds `sizeof(int*)` bytes to `p`. – Some programmer dude Jul 23 '13 at 13:01
4

With the line

int **p=&m

you create a pointer to a pointer to an integer.

Then, you add one to the address - one memory address, that is, not one times the number of bytes to point to the next integer.

Then you deference it twice:

  • both dereferences will return unspecified values, so the second dereference may break memory boundaries for the OS you are using,
  • both times it will be off boundary alignmemnt, which may cause issues in some OSes.
Neil Townsend
  • 6,024
  • 5
  • 35
  • 52
2
int **p=&m;

p points to address, where m is placed:

... |  m  | sth | ... |  p  | ...
       ^                 V
       |_________________|

Now, increment it:

... |  m  | sth | ... |  p  | ...
             ^           V
             |___________|

So, now p points to sth. What is sth? Nobody knows. But you're trying to get access to the address sth contains. This is undefined behavior.

awesoon
  • 32,469
  • 11
  • 74
  • 99
0

Here int **p=&m;. p points to m. Then when p = p + 1; p will point to the address next to m (integer). That address may not be accessible.

Thanushan
  • 532
  • 2
  • 8