WRICK
WRICK

Reputation: 31

strange output issue in c

1)  #include <stdio.h>
    int main()
  {
       int a[5] = {1,2,3,4,5};
       int *ptr = (int*)(&a+1);
        printf("%d %d", *(a+1), *(ptr-1));
        return 0;
   }

the output is 2 5. &a means the address of a[0] so &a+1 should be the address of a[1]. So ptr should hold the address of a[1]. *(a+1) will be 2 but *(ptr-1) should also be 2. I can't understand how is it printing 5.

Upvotes: 0

Views: 164

Answers (4)

Achal
Achal

Reputation: 11921

Firstly, you said: &a means the address of a[0] so &a+1 should be the address of a[1] ? No you are wrong. &a means address of a not a[0]. And &a+1 means it increments by whole array size not just one elements size and a+1 means address of a[1].

Here

int a[5] = {1,2,3,4,5};

lets assume base address of a is 0x100

    --------------------------------------
    |   1   |   2   |   3  |   4   |   5  |
    --------------------------------------
   0x100   0x104   0x108   0x112  0x116 ..  
   LSB
    |
    a  

When you are doing

int *ptr = (int*)(&a+1);

Where ptr points ? first (&a+1) performed and it got increments by whole array size i.e

(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
       == 0x120

So now ptr points to

    --------------------------------------
    |   1   |   2   |   3  |   4   |   5  |
    --------------------------------------
   0x100   0x104   0x108   0x112  0x116  0x120  
    a                                     |
                                         ptr points here

Now when you print like

printf("%d %d", *(a+1), *(ptr-1));

Here

*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
       == *(0x104) /* value at 0x104 location */
       == 2 (it prints 2)

And

*(ptr-1)  == *(0x120 - 1*4)
          == *(0x116) /* prints value at 0x116 memory location */
          == 5

Note :- Here

int *ptr = (int*)(&a+1);

type of &a is of int(*)[5] i.e pointer to an array of 5 elements but you are casting as of int* type, as pointed by @someprogrammerdude it breaks the strict aliasing and lead to undefined behavior.

Correct one is

int *ptr = a+1;

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409136

This expression is the important thing: &a+1. That is actually (&a)+1 which is equal to (&a)[1] which will be a pointer to one element past the end of the array.

If we look at it more "graphically" it looks like this, with relevant pointers added:

+------+------+------+------+------+
| a[0] | a[1] | a[2] | a[3] | a[4] |
+------+------+------+------+------+
^      ^                           ^
|      |                           |
|      &a[1] (equal to *(a + 1))   |
|                                  |
&a[0] (equal to a)                 |
|                                  |
&a                                 &a+1

First of all, the type of &a is int (*)[5], so your cast to int * will break strict aliasing (which leads to undefined behavior).

Second of all, since ptr is pointing, effectively, to what would be a[5] then ptr - 1 will point to a[4].

Upvotes: 4

dbush
dbush

Reputation: 223699

&a is not the address of a[0] but the address of a. The values may be the same but the types are different. That is important when it comes to pointer arithmetic.

In the expression &a + 1, you first have &a which has type int (*)[5], i.e. a pointer to an array of size 5. When you add 1 to that it actually adds sizeof(a) bytes to the pointer value. So &a + 1 actually points to one byte past the end of the array. You then cast this expression from int (*)[5] to int * and assign it to ptr.

When you then evaluate *(ptr - 1), the - operator subtracts 1 * sizeof(int) from the byte value of ptr so it now points to the last element of the array, i.e. 5, and that is what is printed.

Upvotes: 2

Lundin
Lundin

Reputation: 213418

&a gives the address of the array as an array pointer, int (*)[5]. It is a pointer type that points at the array as whole, so if you do pointer arithmetic with it, +1 will mean +sizeof(int[5]) which is not what you intended.

Correct code:

int *ptr = a+1;

Notably, the cast (int*) was hiding this bug. Don't use casts to silence compiler errors you don't understand!

Upvotes: 2

Related Questions