The below post is just something i thought of contributing here for young( or old ) members starting out in C.
In (effectively) 3 lines of code , i hope to give an intro about pointer arithmetic and how endian-ness in windows affects the output.

#include<stdio.h>
int main(void){
    int a = 66561;
    char *c = &a;
    int i;
    for(i=0 ; i < 4 ; i++) printf("%d\n",*(c+i));
}

This gives an output of

1
4
1
0

Why ?
Well , 66561 in binary is 00000000-00000001-00000100-00000001. (iv separated each byte with a '-' )
But , in windows , which is a little endian system , the above binary is stored in reverse order ( little end coming first ) in memory as :

00000001-00000100-00000001-00000000.

So , when you go reading one byte at a time , it is read as 1 , 4 , 1 and 0.

However , you'll notice that i did this using a character pointer , not by creating any character array. Well , that's because you dont need to do that.

If u write : int arr[5] , then arr is same as saying &arr[0] they both point to the starting address of the memory occupied by what we take as an array. In the same way , if u say int *a = 5 , then a is the same as arr or &arr[0]. its just a pointer that points to a certain memory.

Applying this concept , when i write : char *c = &a; what im doing is making the char pointer c point to the starting address of the 4 byte int a. Then , when i say printf("%d\n",*(c+i)) , what happens is that in each iteration , the program moves forth by as many bytes as the type of variable c happens to be. In this case , its 1 byte. So in four steps , the program moves one byte at a time , reading in the same way as it would if it was traversing an array.

In fact , you can just as well write printf("%d",c[1]) instead of printf("%d\n",*(c+i)) , Both mean the same thing to the program : "Go one byte (size of char) at a time from the base address (which is the start of the 4 byte int) "

Lastly , You do get a warning : initialization from incompatible pointer type when compiling , but thats coz your tricking the program to thing the value contained by the int is actually a char.In more complicated code , these kinda stuff can be hard to debug if a crash occurs , so the compiler warns you before hand.

ps : Experienced C folks out there , do let me know if i made some mistakes. Also feel free to improve the answer :)

Hope this helps someone
Somjit.

Edited 2 Years Ago by somjit{}

On a side note, the technique you're showing is called type punning. It's rather common in lower level code. If you're feeling frisky, an example of union-based punning to break down a floating-point value can be found in one of my teaching libraries here and here.

In the same way , if u say int *a = 5 , then a is the same as arr or &arr[0]. its just a pointer that points to a certain memory.

Noting, of course, that an array is not a pointer. Though an array name in most contexts is converted to a pointer.

In fact , you can just as well write printf("%d",c[1]) instead of printf("%d\n",*(c+i)) , Both mean the same thing to the program

Further solidifying the equivalence, you can also write printf("%d", 1[c]) because addition is commutative. Don't do that in real code though, it's an interesting yet useless trick.

Lastly , You do get a warning : initialization from incompatible pointer type when compiling

Which is cleared up with a cast. It's important to understand the warnings and avoid them where necessary. But if the warning is known to be spurious, it's best to make it go away so that the compilation log is clean. That way real warnings and errors stand out more.

Comments
thanks for the type punning side note! now i know what to search for :)

Noting, of course, that an array is not a pointer. Though an array name in most contexts is converted to a pointer.

Can you elaborate that part a bit ?

Regarding the cast , kept it out coz felt like its a different pond ( or lake , or sea ) altogether.. but thanks for seamlessly joining that in. Couldn't have done it near as well !

Can you elaborate that part a bit ?

It's a common misunderstanding that arrays and pointers are equivalent, which causes confusion when you reach a point where object context rules (such as with the sizeof operator). The reason for the misunderstanding is that in value context, the name of an array is converted to a pointer to the first element:

int a[5];

// Prints the same address for both
printf("%p\n", (void*)a);
printf("%p\n", (void*)&a[0]);

int *p = a; // Compatible types, so no cast needed

Most of the time this conversion applies. However, this is not the case in object context, otherwise sizeof wouldn't work correctly:

printf("%zd\n", sizeof(a)); // Works like a champ

With a pointer you'd get the size of the pointer, and with an array you'd get the collective size of the elements in the array as a whole.

There are three object contexts for an array:

  • As an operand to the sizeof operator.
  • As an operand to the address-of (&) operator.
  • As a string initializer.

Well , i knew that sizeof(array) returns memory occupied , but if somebosy had asked me why thats happening , wouldn't have been able to answer properly i guess. Now i know what to say :) thanks :)

This question has already been answered. Start a new discussion instead.