将指向整数的指针强制转换为指向char的指针时会发生什么?
int i=40; char *p; p=(char *)&i;//What actually happens here? printf("%d",*p);
什么是输出? 请帮忙!
p=(char *)&i;//What actually happens here?
它接受i
的地址并将其转换为char
指针。 所以*p
的值现在是i
的第一个字节。 这个价值是什么,取决于平台。
让我们首先看一下i
和p
的内容将如何在内存中布局(假设是big-endian顺序):
项目地址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 *
pointer to int
。 强制转换将类型从int *
转换为char *
,结果分配给p
。
以下是分配后内存中的内容:
项目地址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
类型提升为char
类型。
因此对于这种特殊情况,输出为“0”。 如果订单是little-endian,那么地图就会像
项目地址0x03 0x02 0x01 0x00 ---- ------- ---------------------- i 0x08000000 0x00 0x00 0x00 0x28 p 0x08000004 0x08 0x00 0x00 0x00
输出为“40”。
请注意,整个示例假设整数和字符指针具有相同的大小和布局; 这并不能保证在任何地方都是真实的(参见在线C标准(n1256草案) ,第6.2.5节,第27段),所以你不能按照你期望的方式依赖这个工作(假设我认为这是正确的) int
和char
不是标准定义的兼容类型,但我可能错了)。 一般来说,打字是不安全的。
这个给你
int i = 40;
//为整数i分配内存并为其赋值40
char *p = (char*)&i;
所以在这里你要定义一个指针变量并在将其转换为char*
之后为其分配i的地址
假设i
被分配在1021 address
所以p将具有该字节的限制为1字节,因此它应该first 8 bit from the representation of 40;
保持first 8 bit from the representation of 40;
因为40已经覆盖了2字节的前8位,它将保持40当量的等效数,但是当你用%d
打印它时,它会打印40
;
这取决于。 在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或更大,结果将是不正确的。
当int指针被类型化为char时会发生什么? 还有另一个问题标记为重复,我试着解释一下。
$ cat ac #include int main(){ int a; char *x; x = (char *) &a; a=512; x[0]=1; x[1]=2; printf("%d\n",a); return 0; }
编译并运行:
$ gcc ac && ./a.out 513
为什么是513? 我们可以使用gdb来查看根本原因。
$ gcc ac -g && gdb ./a.out (gdb) list 1 #include 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);
在交流的第8行设置一个断点,然后运行
(gdb) b ac:8 Breakpoint 1 at 0x40113d: file ac, line 8. (gdb) run
程序停止在断点处,打印变量a的内存地址。
(gdb) p &a $2 = (int *) 0x7fffffffd9d4 (gdb) px $3 = 0x7fffffffd9d4 ""
变量a的内存地址是0x7fffffffd9d4,变量x的值是相同的。
在显示内存内容之前,让我们了解512格式的hex格式,它是:
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"