1

In this program all three addresses which I mention refer to the first element of the array but why don't I get the value of the first element of the array when I dereference them?

int main() { int a[5] = {1,2,3,4,5}; printf("address a = %d\n",a); printf("address of a[0] = %d\n",&a[0]); printf("address of first element = %d\n",&a); printf("value of first element of the array a =%d\n",*(a)); printf("first element =%d\n",*(&a[0])); printf("a[0] = %d\n",*(&a));//this print statement again prints the address of a[0] return 0; } 

I get address of the first element of the array a for the first 3 print statements and when I dereference all the 3 I get values only for the fourth and fifth print statements and not for the sixth print statement (which is accompanied with a comment).

5
  • 2
    BTW almost all your printf are invalid. %p is the correct specifier for pointers (you'd have to cast to void*). The only valid one is the 5th, since *a is indeed an int. Commented Aug 20, 2012 at 6:45
  • Don't use %d for printing pointers. Commented Aug 20, 2012 at 6:46
  • 1
    @FerdinandBeyer &a is not int**. It is int(*)[5] which is something completely diffent. Commented Aug 20, 2012 at 6:46
  • 2
    The C FAQ could be a good reference for arrays versus pointers and questions like that c-faq.com Commented Aug 20, 2012 at 6:48
  • @FerdinandBeyer, really completely different: the difference is p->data versus p->p->data. In one case the data is at one hop for the other at two hops. You need to understand that arrays are not pointers in C. Commented Aug 20, 2012 at 6:51

4 Answers 4

5

Things to remember:

  1. Name of the array is the address of its first element

So, as the array name is a, then, printing a would give you the address of a[0] (which is also the address of the array too) i.e. you will get the values of &a[0] (same as a) and &a to be the same

Now, you are aware that a and &a[0] refer to the first element, you can dereference the first element in 3 ways:-

  • *a
  • *(&a[0])
  • a[0] - Note that internally, this gets transformed into: *(a+0)

Things to remember:

   2. Adding an integer to a pointer takes the pointer to the next element

Here, &a points to the address of the whole array. Although the value of &a is the same as &a[0] and a, but, it is a pointer to the array, not pointer to the first element. So, if you add 1 to &a i.e. &a + 1, you'll go beyond this array.

SImilarly, as &a[0] and a are pointers to the first element, adding 1 to them will give you the next element of the array (if there are more than 1 items defined in the array). i.e. (a+1) and &a[0] + 1 point to the next element from the first element. Now, for dereferencing them, you can use:

  • *(a+1)
  • *(&a[0] +1)
  • a[1] - Note that internally, this gets transformed into: *(a+1)

Adding more information to remove the following doubt:

If, as this answer states, the name of the array were the address of its first element, then &a would be the address of the address of the first element.

The answer to this doubt is both No and Yes.

  • No because there is nothing like address of the address.
  • For understanding yes, consider the following situation:

    Imagine that you have 10 boxes of chocolates and each box contains 5 chocolates (fitted in a line inside the box) and that the boxes are lined up.

5 boxes of 5 chocolates each

Ok, enough chocolates to explain.

Here, So, boxes represent arrays of chocolates. Thus, we have with us 5 boxes of 5 chocolates each. The declaration for that would be:

Translating it to C, just assume that a is an array with 5 numbers.

-Now, if I ask you to tell me the location of the first box, then, you will refer to it as &a. If I ask you to get me the location of second box, then, you'll refer to it as &a +1.

  • If I ask you to get me the location of first chocolate in the first box, then you'll refer to it as &a[0] or (a+0) or a.
  • If I ask you to get me the location of second chocolate in the first box, then you'll refer to it as &a[1] or (a+1) or a+1. Note: In (a+1), as a is the name of the array, it is the address of the first element, which is an integer. So, increasing a by 1, means the address of the second element.
  • If I ask you to get me the location of the second box of chocolates, then, you'll refer to it as (&a+1)
  • If I ask you to get me the location of the first chocolate in the second box of chocolates, then, you'll refer to it as *(&a+1) or *((&a+1) + 0)
  • If I ask you to get me the location of the third chocolate in the second box of chocolates, then, you'll refer to it as (*(&a+1))+2
Sign up to request clarification or add additional context in comments.

2 Comments

If, as this answer states, the name of the array were the address of its first element, then &a would be the address of the address of the first element. It is not.
@Eric: I have answered to your question briefly in my answer by editing it. Please go through it once
0

To answer just your question, by definition the operators * and & are such that they cancel out. Taking the address of a variable and then dereferencing gives you back the variable. Here this is is an array, a. In most contexts arrays "decay" to pointers so what you then see again is the address of the first element.

2 Comments

please look into the question,i have added ( )which separates the * and & operator so that they cannot cancel out directly.
@random, they don't cancel out syntactically but semantically. One is is the inverse of the other, that is all. Is as if you did 10+1-1, the result is the same regardles if you put parenthesis in there.
0

The C standard specifies that an expression that has type “array of type” is converted to type “pointer to type” and points to the initial element of the array, except when the expression is the operand of & (or three other exceptions, noted below but not relevant to this question). Here is how this applies to your examples:

  • a is an array of int. It is converted to pointer to int. The value is the address of the initial element of a.
  • In &a[0], a[0] is processed first. a is again converted to pointer to int. Then the subscript operator is applied, which produces an lvalue for the initial element of the array. Finally, & takes the address of this lvalue, so the value is the address of the initial element of a.
  • In &a, a is the operand of &, so a is not converted to a pointer to int. It remains an array, and &a takes its address. The result has type “pointer to array of int”, and its value is the address of the array, which equals the address of the initial element.

For completeness: The relevant rule in the C standard is 6.3.2.1 paragraph 3. The exceptions are:

  • The array expression is the operand of &.
  • The array expression is the operand of sizeof.
  • The array expression is the operand of _Alignof.
  • The array expression is a string literal used to initialize an array.

The last means that in char s[] = "abc";, "abc" is not converted to a pointer to the initial element; it remains an array, which is used to initialize s.

Comments

-1

The a is a pointer and a[0] is *(a+0). So when you write *(&a), you aren't dereferencing it.

3 Comments

@ Jeff: a is definitely a pointer to the first element of the array. As per C norms, the name of the array is the address of its first element.
@GodMan: The name of the array is not the address of its first element. The rule in the C standard is that an expression (not necessarily a name) of array type is converted to a pointer to the initial element in most situations, but there are exceptions. Because there are exceptions, you cannot treat the name of the array as identical to a pointer to the initial element.
To add to that, the & operator is exactly one of these exceptions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.