Kuntal Basu
Kuntal Basu

Reputation: 830

Why this arr[0] is not equal to arr+0?

Hi I got confused to get the explanation for this below, can anyone explain it to me? Thanks in advance.

#include<stdio.h>
int main(){
    char *arr,c;
    arr = &c;

    arr++;
    *arr = 'a';

    arr++;
    *arr = 'b';

    arr++;
    *arr = 'c';

    arr--;
    arr--;

    printf("\narr 1 = %c",arr);
    printf("\narr 2 = %c",arr[1]);
    printf("\narr 3 = %c",arr[2]);
    getch();
    return 1;
    }

Output is :
arr 1 = a
arr 2 = b
arr 3 = c

but if the change the line:

printf("\narr 1 = %c",arr);

with

printf("\narr 1 = %c",arr[0]);

Now Output is:
arr 1 =  
arr 2 = b
arr 3 = c

why 'a' is not getting printed.?

*For all those who are questioning the program as bad coding.. I know its not a good coding practice to use pointer like this, But my question is why arr[0] is not printing anything where as arr[1] & arr[2] is printing what is assigned?

Upvotes: 1

Views: 1293

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222941

In the first version of the program, what likely happens is:

  • The compiler puts c at some address on the the stack, say 1003 (a single byte).
  • The compiler puts arr at some address on the stack, say 1004-1007 (four bytes).
  • The statement arr = &c; puts the address of c, 1003, into arr.
  • The statement arr++; adds one to arr, so it is now 1004 instead of 1003.
  • The statement *arr = 'a'; writes 'a' to the place where arr points. This is now behavior that is undefined by the C standard. When arr was set to &c, there was only one byte in the object at that location, and the C standard does not guarantee what happens when you write to other locations after incrementing that address outside the object.
  • As it happens in this instance, 1004 points into arr, so you are writing 'a' into one of the bytes of arr. This horribly alters the address that was in arr.
  • Then arr++; increments the address again, and *arr = 'b'; writes 'b' somewhere. We do not know where, because arr has a bad value in it.
  • Then arr++; increments the address again, and *arr = 'c'; writes 'c' somewhere. We do not know where.
  • Then arr--; and arr--; return the address to the value it had after 'a' was written.
  • Then the first printf call passes the value in arr to be printed with a “%c” specifier. “%c” is for printing a character, but the arr you pass it is a pointer. However, you previously wrote 'a' into the pointer, so the value of the pointer has 'a' in one of its bytes.
  • As it happens, when the “%c” specifier is used with a pointer, this implementation of printf prints one of the bytes in the pointer value, in this case the same byte where you wrote 'a'. So “a” is printed. You cannot rely on this happening in other C implementations. This happened in this case only because the compiler happened to place arr in memory just after c in memory, so the statement *arr = 'a'; wrote 'a' into arr. This will not happen in all C implementations. You got “lucky.”
  • After the write of 'a' into arr, arr is pointing somewhere, although we do not know where. Let’s call this location x.
  • The statements arr++; and *arr = 'b'; wrote 'b' to the location x+1.
  • The statements arr++; and *arr = 'c'; wrote 'c' to the location x+2.
  • Then two arr--; statements returned arr to point to x. So arr[1] is the character at x+1, which is 'b', and arr[2] is 'c'. Passing these to printf to be printed with “%c” prints “b” and “c”.

In the second version of the program, when arr[0] is passed to printf:

  • The value of arr is the value that was formed by writing 'a' into one of its bytes. This is some “random” address, pointing to no location we have controlled. Apparently there is a 0 character there, or some other non-printing character, so, when arr[0] is passed to printf, nothing is printed.
  • Passing arr[1] and arr[2] print “b” and “c” because the code wrote 'b' and 'c' to those locations.

Upvotes: 9

Luchian Grigore
Luchian Grigore

Reputation: 258618

This is just undefined behavior - arr++; *arr = 'a'; is illegal because arr points to a single char. Anything can happen.

Upvotes: 6

user529758
user529758

Reputation:

arr is not equivalent to arr[0], since arr[0] dereferences the array. The correct equivalent would be &arr[0].

By the way, what you're doing invokes undefined behavior, since after incrementing arr, it points to an invalid memory location - originally it points to a single character, so you can't assume there's anything after it.

Upvotes: 6

Related Questions