What actually happens when a pointer to integer is cast to a pointer to char?

13,253

Solution 1

p=(char *)&i;//What actually happens here?

It takes the address of i and casts it to a char pointer. So the value of *p is now the first byte of i. What that value is, is platform dependent.

Solution 2

Let's start by looking at how the contents of i and p would be laid out in memory (assuming big-endian order):

Item               Address               0x00  0x01  0x02  0x03
----               -------               ----------------------
   i               0x08000000            0x00  0x00  0x00  0x28
   p               0x08000004            0x??  0x??  0x??  0x??

Since p is being declared as an auto variable, it's not initialized to anything and contains a random bit pattern represented by 0x??.

In the line

p = (char *)&i;

the expression &i evaluates to the address of i, or 0x08000000, and its type is pointer to int, or int *. The cast converts the type from int * to char *, and the result is assigned to p.

Here's how things look in memory after the assignment:

Item               Address               0x00  0x01  0x02  0x03
----               -------               ----------------------
   i               0x08000000            0x00  0x00  0x00  0x28
   p               0x08000004            0x08  0x00  0x00  0x00

So the value of p is now the address of i. In the line

printf("%d", *p);

the type of the expression *p is char, and its value is whatever is stored in address 0x08000000, which in this particular case is 0. Since printf is a variadic function, the value of *p is promoted from type char to type int.

So for this particular case, the ouput is "0". If the order were little-endian, the map would look like

Item               Address               0x03  0x02  0x01  0x00
----               -------               ----------------------
   i               0x08000000            0x00  0x00  0x00  0x28
   p               0x08000004            0x08  0x00  0x00  0x00

and the output would be "40".

Note that this whole example assumes that integer and character pointers have the same size and layout; that's not guaranteed to be true everywhere (see the Online C Standard (n1256 draft), section 6.2.5, paragraph 27), so you can't rely on this working everywhere the way you expect (assuming I'm correct in thinking that int and char are not compatible types as defined by the standard, but I could be wrong on that). Type punning in general is not safe.

Solution 3

here you are

int i = 40; //allocating memory for integer i and assigning value 40 to it

char *p = (char*)&i; 

so here you are defining a pointer variable and assigning it the address of i after casting it to char*

suppose i is allocated at 1021 address so p will have that address with the limit of 1 byte so it should hold first 8 bit from the representation of 40;

as 40 has been cover under first 8 bit of 2 byte it will hold a char equivalend of 40 but as you are printing it with %d it shopuld print 40;

Solution 4

It depends. On Windows, the output will be 40, but this is just because of a lot of coincidences:

First of all, printf does not (cannot) check the type of its arguments, so since it sees %d in the format string, it assumes that the given argument is an int. Although *p is only a char, the result is promoted to an int (as is for every argument that is not specified in the function prototype).

Second, p will point to the memory taken by the variable i, but since it's a char pointer, it will only take one byte from the memory of i. Since Windows/Intel uses Least-Significant-Byte first convention, 40 will be stored as byte pattern "40 0 0 0" so, since *p takes the first byte (char), the result will be 40. If i would have the value 256 or bigger, the result would be incorrect.

Solution 5

What happens when int pointer is typecasted to char? There is another question marked duplicated to here, I try to explain for it.

$ cat a.c
#include <stdio.h>

int main(){
    int a;
    char *x;
    x = (char *) &a;
    a=512;
    x[0]=1;
    x[1]=2;
    printf("%d\n",a);
    return 0;
}

Compile and run:

$ gcc a.c && ./a.out
513

Why it is 513? We can use gdb to see the root cause.

$ gcc a.c -g && gdb ./a.out
(gdb) list
1       #include <stdio.h>
2
3        int main(){
4            int a;
5            char *x;
6            x = (char *) &a;
7            a=512;
8            x[0]=1;
9            x[1]=2;
10           printf("%d\n",a);

set a break point at line 8 of a.c, and run

(gdb) b a.c:8
Breakpoint 1 at 0x40113d: file a.c, line 8.
(gdb) run

once program stop at break point, print variable a's memory address.

(gdb) p &a
$2 = (int *) 0x7fffffffd9d4
(gdb) p x
$3 = 0x7fffffffd9d4 ""

variable a's memory address is 0x7fffffffd9d4, and variable x's value is the same.

before show memory content, let's understand how 512 in hex format, it is:

00 00 02 00

and x86 is little endian, so in memory it should be:

[higher address] 00 02 00 00 [lower address]

let's show the real memory, just as same as we thought.

(gdb) x/4xb 0x7fffffffd9d4
0x7fffffffd9d4: 0x00    0x02    0x00    0x00

then, show memory address of x[0] and x[1], and convert the memory content to real value, it should not difficult to understand why print out 513.

(gdb) p &x[0]
$4 = 0x7fffffffd9d4 ""
(gdb) p &x[1]
$5 = 0x7fffffffd9d5 "\002"
Share:
13,253

Related videos on Youtube

vas
Author by

vas

Updated on June 04, 2022

Comments

  • vas
    vas almost 2 years
    int i=40;
    char *p;
    p=(char *)&i;//What actually happens here?
    printf("%d",*p);
    

    What will be the output? Please help!

  • Tadeusz A. Kadłubowski
    Tadeusz A. Kadłubowski over 13 years
    Most likely that would be either 0 or 40 (depending on endianness of the machine).
  • JeremyP
    JeremyP over 13 years
    Except that the machine might be big endian in which case, you'll get 0.
  • Keith Thompson
    Keith Thompson almost 13 years
    Your description assumes that int* and char* pointers have the same size and layout, but the visible behavior of the program doesn't. The C Standard guarantees that any object can be accessed as an array of characters, so the OP's code will access the first (lowest-addressed) byte of i. The value of that byte, as others have pointed out, depends on the implementation.
  • Suraj Jain
    Suraj Jain over 7 years
    @KeithThompson Why is cast needed , what is the difference between char *p = (char *) &i and char *p = &i ?
  • Suraj Jain
    Suraj Jain over 7 years
    Why is cast needed , what is the difference between char *p = (char *) &i and char *p = &i ?
  • Suraj Jain
    Suraj Jain over 7 years
    Why is cast needed , what is the difference between char *p = (char *) &i and char *p = &i ?
  • Suraj Jain
    Suraj Jain over 7 years
    Why is cast needed , what is the difference between char *p = (char *) &i and char *p = &i ?
  • Keith Thompson
    Keith Thompson over 7 years
    @SurajJain: The difference is that char *p = (char *) &i;islegal, and char *p = &i;is not. There is no implicit conversion between char* and int* (though some compilers might allow it, preferably with a warning). Pointer conversions can be dangerous, letting you treat an object of one type as if it were of another type, so the language requires such conversions to be explicit.
  • Suraj Jain
    Suraj Jain over 7 years
    @KeithThompson If the compiler allows it with a waring , like "initialisation from incompatible type " then are they same , do they behave same. This is bugging me from a long time.
  • Keith Thompson
    Keith Thompson over 7 years
    @SurajJain: Early versions of C were more lax about implicit conversions. The rules were tightened up by the 1989 ANSI standard, but many compilers permit such conversions to avoid breaking old code. char *p = &i; is a constraint violation, requiring a diagnostic. That diagnostic (unfortunately, IMHO) can be a non-fatal warning. It's not clear whether the behavior is defined or not. You need to take warnings seriously; treat them as fatal errors unless you're sure that your code is right and the compiler is wrong.
  • Suraj Jain
    Suraj Jain over 7 years
    @KeithThompson Ok , Sir , can you check this question , i asked this long back , i have answered it when things were clear to me , i just want to make sure that i do not misead anyone. stackoverflow.com/questions/34826036/…