将指向整数的指针强制转换为指向char的指针时会发生什么?

时间:2010-09-20 06:44:07

标签: c casting

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

输出是什么?请帮忙!

5 个答案:

答案 0 :(得分:7)

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

它需要i的地址并将其强制转换为char指针。因此*p的值现在是i的第一个字节。这个价值是什么,取决于平台。

答案 1 :(得分:5)

让我们首先看看ip的内容将如何在内存中布局(假设是大端序):

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 intint *。演员表将类型从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"