int i=40;
char *p;
p=(char *)&i;//What actually happens here?
printf("%d",*p);
输出是什么?请帮忙!
答案 0 :(得分:7)
p=(char *)&i;//What actually happens here?
它需要i
的地址并将其强制转换为char
指针。因此*p
的值现在是i
的第一个字节。这个价值是什么,取决于平台。
答案 1 :(得分:5)
让我们首先看看i
和p
的内容将如何在内存中布局(假设是大端序):
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---------------------- i 0x08000000 0x00 0x00 0x00 0x28 p 0x08000004 0x?? 0x?? 0x?? 0x??
由于p
被声明为自动变量,因此它未初始化为任何内容,并且包含由0x??
表示的随机位模式。
在第
行p = (char *)&i;
表达式&i
的计算结果为i
或0x08000000的地址,其类型为pointer to int
或int *
。演员表将类型从int *
转换为char *
,结果将分配给p
。
以下是分配后内存中的内容:
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---------------------- i 0x08000000 0x00 0x00 0x00 0x28 p 0x08000004 0x08 0x00 0x00 0x00
因此p
的值现在是i
的地址。在行
printf("%d", *p);
表达式*p
的类型是char
,其值是存储在地址0x08000000中的任何值,在此特定情况下为0.因为printf
是可变参数函数, *p
的值从类型char
提升为类型int
。
因此对于这种特殊情况,输出为“0”。如果订单是little-endian,则地图看起来像
Item Address 0x03 0x02 0x01 0x00 ---- ------- ---------------------- i 0x08000000 0x00 0x00 0x00 0x28 p 0x08000004 0x08 0x00 0x00 0x00
,输出为“40”。
请注意,整个示例假设整数和字符指针具有相同的大小和布局;这并不能保证在任何地方都是真实的(参见Online C Standard (n1256 draft),第6.2.5节,第27段),所以你不能按照你期望的方式依赖这个工作(假设我认为{{{ 1}}和int
不是标准定义的兼容类型,但我可能错了)。一般来说,打字是不安全的。
答案 2 :(得分:2)
你在这里
int i = 40;
//为整数i分配内存并为其赋值40
char *p = (char*)&i;
所以在这里你要定义一个指针变量,并在将其转换为char*
之后为其指定地址
假设i
分配1021 address
,因此p将具有1字节限制的地址,因此它应该保留first 8 bit from the representation of 40;
因为40已经覆盖了2字节的前8位,所以它将保持40等于char,但是当你用%d
打印它时,它会打印40
;
答案 3 :(得分:1)
这取决于。在Windows上,输出将是40,但这只是因为很多巧合:
首先,printf没有(不能)检查其参数的类型,因此它在格式字符串中看到%d,它假定给定的参数是int。虽然* p只是一个char,但结果会被提升为int(就像函数原型中未指定的每个参数一样)。
其次,p将指向变量i占用的内存,但由于它是一个char指针,因此它只占用i的内存中的一个字节。由于Windows / Intel使用Least-Significant-Byte第一个约定,40将被存储为字节模式“40 0 0 0”,因此,因为* p取第一个字节(char),结果将是40.如果我将拥有值256或更大,结果将是不正确的。
答案 4 :(得分:0)
What happens when int pointer is typecasted to char? 这里有另一个标记为重复的问题,我尝试为其解释。
$ 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;
}
编译并运行:
$ gcc a.c && ./a.out
513
为什么是513?我们可以使用gdb查看根本原因。
$ 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);
在a.c的第8行设置一个断点,然后运行
(gdb) b a.c:8
Breakpoint 1 at 0x40113d: file a.c, line 8.
(gdb) run
一旦程序在断点处停止,打印变量a的内存地址。
(gdb) p &a
$2 = (int *) 0x7fffffffd9d4
(gdb) p x
$3 = 0x7fffffffd9d4 ""
变量a的内存地址为0x7fffffffd9d4,变量x的值相同。
在显示内存内容之前,让我们了解十六进制为512的方式:
00 00 02 00
并且x86是小端,因此在内存中应该是:
[higher address] 00 02 00 00 [lower address]
让我们展示真实的记忆,就像我们想象的一样。
(gdb) x/4xb 0x7fffffffd9d4
0x7fffffffd9d4: 0x00 0x02 0x00 0x00
然后,显示x [0]和x [1]的内存地址,并将内存内容转换为实数值,应该不难理解为什么要打印513。
(gdb) p &x[0]
$4 = 0x7fffffffd9d4 ""
(gdb) p &x[1]
$5 = 0x7fffffffd9d5 "\002"