0

I have code something like this

int main () 
 { 
     unsigned int x [4] [3] = 
     {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};
     printf("%u, %u, %u", x + 3, * (x + 3), * (x + 2) + 3); 
 }

The output for all of the 3 values are same can anyone tell me why.?

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Using the wrong format specifier is undefined behaviour. – mch Aug 04 '16 at 11:17
  • How come wrong format specifier %u is for unsigned int. –  Aug 04 '16 at 11:22
  • `x+3` has type `unsigned int (*)[3]` (a pointer),`*(x+3)` and `*(x+2)+3` have type `unsigned int *`. All 3 are no `unsigned int`, but pointers, so you should use `%p` and cast to `(void*)`. – mch Aug 04 '16 at 11:26
  • @PrajwalBhat, to answer your comment about array indexing being pointer arithmetic in disguise: http://stackoverflow.com/a/14111286/817643 – StoryTeller - Unslander Monica Aug 04 '16 at 11:30

3 Answers3

1

First of all - as others have pointed out - you need to use the correct format specifiers, and cast to these values to pointers.


Now as to why all of them give same value.

Here x is an array. And the type of its elements are unsigned int[3]. i.e. x is an array of unsigned int[3] arrays.

First, x + 3 gives the address of fourth element in your array. That is the address of {10, 11, 12}. The address of this array in memory will be the address of its first element in memory. That is the address of 10 in memory. Note that this value is int (*) [3], i.e. address of an unsigned int[3] array.

Second, * (x + 3) is equivalent to x[3], which is the fourth element, which is unsigned int[3]. It is the array {10, 11, 12}. This value is pointing to the first element of array {10, 11, 12}. That is, this value is pointing to 10. Note that this value is unsigned int[3].

Third *(x+2) + 3 : Here *(x + 2) is equivalent to x[2] which is an unsigned int[3], which is {7, 8, 9} array , and when you do a + 3 you are again getting the address of 10. Note that this value is unsigned int[3].

So, you see in all three cases your result is the same address in memory, i.e. the address where 10 is stored - even though you are representing different things at different time; unsigned int (*)[3] at first, and unsigned int[3] at second and third.

sps
  • 2,720
  • 2
  • 19
  • 38
0

Distilled undefined behavior:

printf("%u, %u, %u", x + 3, * (x + 3), * (x + 2) + 3);

All extra arguments must be unsigned int, but the 2d is unsigned int (*)[3], the 3d is unsigned int *, the 4th is unsigned int * too.

Sergio
  • 8,099
  • 2
  • 26
  • 52
0

You get wrong values because you do the pointer arithmetic wrong.
x is of type unsigned int[4][3], an array of length 4, each member of which is itself an array of length 3.

So what is x+3? It's the address of the last member in x (remember that the members of x are arrays).
And therefore *(x+3) is itself an array. But what happens to arrays when you pass them as function parameters? They decay into pointers. So you see the address of the first element in that array, mangled by the wrong type specifier in printf.

Okay, let's get to element x[2][3] for instance. It will be an expression of this sort *(*(x+2)+3) which is all in all equivalent to *(&x[0][0] + 2*3 + 3).

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458