What actually happens when a pointer to integer is cast to a pointer to char?
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"
Related videos on Youtube
vas
Updated on June 04, 2022Comments
-
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 over 13 yearsMost likely that would be either 0 or 40 (depending on endianness of the machine).
-
JeremyP over 13 yearsExcept that the machine might be big endian in which case, you'll get 0.
-
Keith Thompson almost 13 yearsYour description assumes that
int*
andchar*
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 ofi
. The value of that byte, as others have pointed out, depends on the implementation. -
Suraj Jain over 7 years@KeithThompson Why is cast needed , what is the difference between
char *p = (char *) &i
andchar *p = &i
? -
Suraj Jain over 7 yearsWhy is cast needed , what is the difference between
char *p = (char *) &i
andchar *p = &i
? -
Suraj Jain over 7 yearsWhy is cast needed , what is the difference between
char *p = (char *) &i
andchar *p = &i
? -
Suraj Jain over 7 yearsWhy is cast needed , what is the difference between
char *p = (char *) &i
andchar *p = &i
? -
Keith Thompson over 7 years@SurajJain: The difference is that
char *p = (char *) &i;
islegal, andchar *p = &i;
is not. There is no implicit conversion betweenchar*
andint*
(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 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 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 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/…