23
#include<stdio.h>
main()
{ int x[3][5]={{1,2,10,4,5},{6,7,1,9,10},{11,12,13,14,15}};


printf("%d\n",x); 
printf("%d\n",*x); }

Here first printf will print the address of first element. So why not the second printf prints the value at the address x i.e the first value. To print the value I need to write **x.

dejavu
  • 3,236
  • 7
  • 35
  • 60

4 Answers4

30

For pointers, x[0] is the same as *x. It follows from this that *x[0] is the same as **x.

In *x[0]:

x is a int[3][5], which gets converted to int(*)[5] when used in expression. So x[0] is lvalue of type int[5] (the first 5-element "row"), which gets once again converted to int*, and dereferenced to its first element.

*x is evaluated along the same lines, except the first dereference is done with an asterisk (as opposed to indexing), and there is no second dereference, so we end up with lvalue of type int[5], which is passed to printf as a pointer to its first element.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • yeah,, but i get the address when i print "x" so when i do the operation *x i should get the value stored at that address... – dejavu Sep 08 '11 at 18:07
  • Yes and no. You really get the value stored at the address, this is the "lvalue of type `int[5]`" I was talking about. However, Arrays are not first class in C, they are passed to functions as pointers to their first element. So `printf` gets the pointer to the first `int` of the 5, which has the same address as the address of the first element of `x`. IOW, `(void*)x == (void*)*x` and that's what you see. – jpalecek Sep 08 '11 at 18:32
6

Arrays, when used as arguments to functions, decay into pointers to the first element of the array. That being said, the type of object that x decays into is a pointer to the first sub-array, which is a pointer to an array of int, or basically int (*)[5]. When you call printf("%d\n",*x), you are not feeding an integer value to printf, but rather a pointer to the first sub-array of x. Since that sub-array will also decay to a pointer to the first sub-array's element, you can do **x to dereference that subsequent pointer and get at the first element of the first sub-array of x. This is effectively the same thing as *x[0], which by operator precedence will index into the first sub-array of x, and then dereference the pointer to the first sub-array's element that the first sub-array will decay into.

Jason
  • 31,834
  • 7
  • 59
  • 78
0

Because of type of *x is 'pointer to array of 5 ints'. So, you need one more dereference to get the first element

PS:

#include <typeinfo>
#include <iostream>

typedef int arr[5]; // can't compile if put arr[4] here
void foo(arr& x)
{
}

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

  std::cout << typeid(*x).name() << std::endl;// output: int [5]

  foo(x[0]);
  return 0;
}

qehgt
  • 2,972
  • 1
  • 22
  • 36
-1

Think about a 2-d array as an array of pointers, with each element in the array pointing to the first element in another array. When you dereference x, you get the value that is in the memory location pointed to by x... a pointer to the first int in an array of ints. When you dereference that pointer, you will get the first element.

Daniel
  • 6,595
  • 9
  • 38
  • 70
  • 3
    This isn't accurate. You can certainly have an effective 2-d jagged array by having an array of pointers, but the actual storage is just row-by-row sequentially, with the dereferencing done by multiplication. – Yuliy Sep 08 '11 at 16:38
  • @Yuliy: I understand that that is not how it is implemented, but it is an easy way to understand why you need to dereference twice. – Daniel Sep 08 '11 at 16:41
  • 1
    @Daniel: Yuliy's point stands. There's already enough confusion among C newbies about this, and already too many trying to allocate a "two dimensional array" as an array of pointers, that any risk of furthering this misunderstanding should be avoided. – R.. GitHub STOP HELPING ICE Sep 08 '11 at 19:33