[c] What are the rules for casting pointers in C?

When thinking about pointers, it helps to draw diagrams. A pointer is an arrow that points to an address in memory, with a label indicating the type of the value. The address indicates where to look and the type indicates what to take. Casting the pointer changes the label on the arrow but not where the arrow points.

d in main is a pointer to c which is of type char. A char is one byte of memory, so when d is dereferenced, you get the value in that one byte of memory. In the diagram below, each cell represents one byte.

-+----+----+----+----+----+----+-
 |    | c  |    |    |    |    | 
-+----+----+----+----+----+----+-
       ^~~~
       | char
       d

When you cast d to int*, you're saying that d really points to an int value. On most systems today, an int occupies 4 bytes.

-+----+----+----+----+----+----+-
 |    | c  | ?1 | ?2 | ?3 |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       (int*)d

When you dereference (int*)d, you get a value that is determined from these four bytes of memory. The value you get depends on what is in these cells marked ?, and on how an int is represented in memory.

A PC is little-endian, which means that the value of an int is calculated this way (assuming that it spans 4 bytes): * ((int*)d) == c + ?1 * 28 + ?2 * 2¹6 + ?3 * 2²4. So you'll see that while the value is garbage, if you print in in hexadecimal (printf("%x\n", *n)), the last two digits will always be 35 (that's the value of the character '5').

Some other systems are big-endian and arrange the bytes in the other direction: * ((int*)d) == c * 2²4 + ?1 * 2¹6 + ?2 * 28 + ?3. On these systems, you'd find that the value always starts with 35 when printed in hexadecimal. Some systems have a size of int that's different from 4 bytes. A rare few systems arrange int in different ways but you're extremely unlikely to encounter them.

Depending on your compiler and operating system, you may find that the value is different every time you run the program, or that it's always the same but changes when you make even minor tweaks to the source code.

On some systems, an int value must be stored in an address that's a multiple of 4 (or 2, or 8). This is called an alignment requirement. Depending on whether the address of c happens to be properly aligned or not, the program may crash.

In contrast with your program, here's what happens when you have an int value and take a pointer to it.

int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
 |    |         x         |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       p

The pointer p points to an int value. The label on the arrow correctly describes what's in the memory cell, so there are no surprises when dereferencing it.

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to pointers

Method Call Chaining; returning a pointer vs a reference? lvalue required as left operand of assignment error when using C++ Error: stray '\240' in program Reference to non-static member function must be called How to convert const char* to char* in C? Why should I use a pointer rather than the object itself? Function stoi not declared C pointers and arrays: [Warning] assignment makes pointer from integer without a cast Constant pointer vs Pointer to constant How to get the real and total length of char * (char array)?

Examples related to casting

Subtracting 1 day from a timestamp date Cast object to interface in TypeScript TypeScript enum to object array Casting a number to a string in TypeScript Hive cast string to date dd-MM-yyyy Casting int to bool in C/C++ Swift double to string No function matches the given name and argument types C convert floating point to int PostgreSQL : cast string to date DD/MM/YYYY