为什么当给 `int` 赋值时 `char` 不会丢失数据?

问题描述 投票:0回答:2

我是一名 C 程序员新手。我定义了两个变量

int x = 0xffffffff
char y = x
,之后我使用
printf("%x\n", y)
函数打印了它;我本以为终端上会出现类似
ff
的内容,但它却在屏幕上打印了
ffffffff
。我想知道当 char 的存储大小为 1 时,
char
如何存储 4 个字节的存储空间。

#include <stdio.h>

int main(void) {
    int x = 0xffffffff;
    char y = x;
    printf("%x\n", y);

    return 0;
}
c integer char
2个回答
5
投票

实际上这里发生了很多事情。 第一:

int x = 0xffffffff;

整数常量

0xffffffff
的值为 4,294,967,295(即 232-1),类型为
unsigned int
,假设
int
是 32 位。

unsigned int
值随后会转换为
int
进行初始化。 这会经历实现定义的转换,在大多数情况下会导致分配值 -1。 该值恰好与二进制补码中的原始值具有相同的表示形式。

然后在这一行:

char y = x;

我们将

y
初始化为值 -1。 该值在
char
的范围内(假设
char
带符号),因此在这种情况下从
int
转换为
char
时,值不会发生变化。 假设采用补码表示,则表示为
0xff

然后当你打印时:

printf("%x\n", y);

因为

printf
是一个可变参数函数,所以类型为
y
的参数
char
在传递给函数之前会被 提升 为类型
int
。 和以前一样,两种类型都可以存储值 -1,因此该值保持不变。

%x
格式说明符需要一个
unsigned int
类型的参数。 由于传递的是
int
而不是
unsigned int
,这在技术上是未定义的行为,但是有符号/无符号不匹配不太可能在任何实际实现中导致问题。

在这种情况下,

int
值-1具有
0xffffffff
的表示形式,当解释为
unsigned int
时将具有该值,因此
ffffffff
就是打印的内容。

所以回答你的问题:

当一个char的存储大小为1时,一个char如何存储4个字节的存储空间。

事实并非如此。 由于相关类型的转换和表示,它看起来就是这样。


1
投票

int x = 0xffffffff;
是实现定义的行为,因为在
0xFFFFFFFF
为 32 位的系统上,
2^31-1
大于
int
int
的大小也是由实现定义的。

如果

char
signed
unsigned
:

,则定义其实现
  • 如果

    char
    signed
    ,则
    char y = x
    将值
    -1
    分配给
    x
    。 在对
    printf()
    的调用中,
    char
    被提升为
    int
    ,其大小已实现定义。 在
    int
    为 32 位的系统上,这被编码为二进制补码
    0xFFFFFFFF
    (截至 C 2023;之前的版本已实现定义),打印为
    ffffffff

  • 如果

    char
    unsigned
    那么它将打印
    ff

格式说明符

%x
需要一个
unsigned int
所以你真的应该在打印到明确定义的行为之前将其转换为这样。 无论哪种情况,
%x
都不会生成
0x
前缀并输出小写字母。

© www.soinside.com 2019 - 2024. All rights reserved.