【问题标题】:assigning 128 to char variable in c将 128 分配给 c 中的 char 变量
【发布时间】:2025-12-23 19:35:11
【问题描述】:

输出是 128 的 32 位 2 的补码,即 4294967168。如何?

#include <stdio.h>
int main()
{
    char a;
    a=128;
    if(a==-128)
    {
        printf("%u\n",a);
    }
    return 0;
}

【问题讨论】:

  • 请注意,4294967168 是 0xFFFFFF80。 -128 是 0x80。在您的平台上,char 是一个签名类型。
  • char 可以签名或未签名,具体取决于系统。如果您的系统将char 定义为有符号,并且您的CHAR_BIT 是8 位,那么您可以在char 中存储的最大正数是127。
  • 使用printf("%u\n",a); 打印负数int(或转换为int 的值)是未定义的行为
  • @4386427 见 C11 §6.5.2.2 6 和 §7.21.6.1 9

标签: c char signed


【解决方案1】:

在打开警告的情况下编译代码会给出:

warning: overflow in conversion from 'int' to 'char' changes value from '128' to '-128' [-Woverflow]

这告诉您分配 a=128; 在您的平台上没有明确定义。

标准说:

6.3.1.3 有符号和无符号整数

1当一个整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新的类型表示,则不变。

2 否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上反复加减一,直到值在新类型的范围内。

p>

3 否则,新类型是有符号的,值不能在其中表示; 结果是实现定义的,或者引发了实现定义的信号

所以我们无法知道发生了什么,因为这取决于您的系统。

但是,如果我们进行一些猜测(请注意这只是猜测):

128 作为 8 位将是 0b1000.0000

因此,当您致电 printf 时,您将转换为 int,会有一个符号扩展,例如:

 0b1000.0000 ==> 0b1111.1111.1111.1111.1111.1111.1000.0000

which - 打印为无符号代表数字 4294967168

【讨论】:

  • 只是为了补充这个答案,在某些架构中,这个char a = 128 可能会产生 0,而不是 -128。 SO上有一个老问题,我找不到。
【解决方案2】:

让你到达那里的步骤顺序是这样的:

  1. 您将 128 分配给 char
  2. 在您的实现中,charsigned char,最大值为 127,因此 128 溢出。
  3. 您的实现将 128 解释为 0x80。它使用补码数学,所以(int8_t)0x80 代表(int8_t)-128
  4. 由于历史原因(与最初开发 C 的 DEC PDP 小型计算机的指令集有关),C 在许多情况下将比int 更短的有符号类型提升为int,包括函数的可变参数,例如@ 987654329@,它没有绑定到原型,仍然使用旧的 K&R C 的参数提升规则。
  5. 在您的实现中,int 是 32 位宽,也是二进制补码,所以 (int)-128 符号扩展为 0xFFFFFF80
  6. 当您进行printf("%u", x) 之类的调用时,运行时会将int 参数解释为unsigned int
  7. 作为无符号 32 位整数,0xFFFFFF80 表示 4,294,967,168。
  8. "%u\n" 格式说明符将其打印出来,不带逗号(或其他分隔符),后跟换行符。

这都是合法的,但许多其他可能的结果也是如此。代码有缺陷且不可移植。

确保你没有超出你的类型范围! (或者如果这是不可避免的,无符号标量的溢出被定义为模算术,所以它的行为更好。)这里的解决方法是使用unsigned char,它的范围从0到(至少)255,而不是@987654339 @。

【讨论】:

    【解决方案3】:

    首先,我希望您能理解,您发布的代码充满了错误,您不希望依赖它的输出。如果您尝试在实际程序中执行任何这些操作,您可能希望以其他一些更明确、更便携的方式来执行此操作。

    所以我假设你只是出于好奇而问,我以同样的精神回答。

    在您的机器上键入 char 可能是一个有符号的 8 位数字。所以它的范围是从-128到+127。所以 +128 不适合。

    当您尝试将值 +128 转换为有符号的 8 位数量时,您最终可能会得到值 -128。这似乎就是你正在发生的事情,因为你的 if 声明显然是成功的。

    接下来我们尝试取值 -128 并将其打印为unsigned int,在您的机器上显然是 32 位类型。它可以保存 0 到 4294967295 范围内的数字,显然不包括 -128。但是无符号整数通常在取模范围内表现得非常好,所以如果我们将 4294967296 与 -128 相加,我们会得到 4294967168,这正是您看到的数字。

    既然我们已经解决了这个问题,让我们在未来解决不适合char 变量的数字,或者使用%u 格式说明符打印带符号的数量。

    【讨论】: