char 数据类型不会通过向保持最大正值的字符添加正数来给出负数

  • 本文关键字:字符 添加 数据类型 char c
  • 更新时间 :
  • 英文 :


我正在尝试将'1'添加到一个具有最大正值的字符中。它给出 0 作为输出而不是给出 -256。

#include <stdio.h>
int main() {
signed char c = 255;
printf("%dn", c + 1 );
}
O / P : 0
c + 2 = 1;
c + 3 = 2;

根据我的理解,一旦达到最大限制(),它应该给出负数()。这是对的吗?我正在 Ubuntu 上测试。

signed char通常是 8 位编码值 [-128...127]。

signed char c = 255;

尝试将c初始化为超出signed char范围的值。

接下来会发生什么是实现行为。 通常255将"mod"256转换为-1的值。

signed char c = 255;
printf("%dn", c     );  // -1 expected
printf("%dn", c + 1 );  //  0 expected

根据我的理解,一旦达到最大限制(),它应该给出负数()。这是对的吗?

不。 将 1 添加到最大值int值是未定义的行为。 没有应该的。 它可能会导致负数,可能不会,可能会退出代码 - 它没有定义。

如果代码是

signed char c = 127;
printf("%dn", c + 1 );

c + 1将为 128,"128n"将被打印,因为c + 1是总和范围内的int运算int

这里有几个隐式转换需要跟踪:

  • signed char c = 255;是将类型为int的常数255转换为较小的signed char。这是"通过赋值进行左值转换"(初始化遵循赋值规则),其中右操作数被转换为左操作数的类型。

    从大型有符号类型到小型有符号类型的实际转换遵循以下规则:

    否则,新类型是有符号的,并且不能在其中表示值;要么 结果是实现定义的信号或实现定义的信号被引发。

    实际上,在二进制补码计算机上发生的非常可能发生的转换是,您最终得到的有符号字符具有等同于0xFF的十进制值,即-1

  • c + 1是具有类型分别为signed charint的两个操作数的操作数的操作数。对于 + 运算符,表示执行通常的算术转换,请参阅隐式类型升级规则。

    这意味着c被转换为int并且对int类型执行操作,这也是结果的类型。

  • printf("%dn", stuff );printf接受可变数量的参数这样的函数会经历一个奇怪的转换规则,称为默认参数升级。如果是整数,则表示执行整数升级(见上面的链接)。如果将c + 1作为参数传递,则类型int,并且不会进行升级。但是,如果您刚刚通过了c,那么根据这些规则,它会隐式提升为int。这就是为什么将%d与字符类型一起使用实际上有效的原因,即使它是打印字符的错误转换说明符。


根据我的理解,一旦达到最大限制(),它应该给出负数()。这是对的吗?

如果您只是执行signed char c = 127; c++;那么这就是签名溢出,未定义的行为,没有可预测的结果。

如果您这样做signed char c = 127; ... c + 1则不会溢出,因为隐式提升到int

如果您这样做unsigned char c = 255; c++;则有一个定义明确的环绕,因为这是一个无符号类型。c将变为零。有符号类型没有这样明确定义的环绕 - 它们而是溢出。

在实践中,有符号数字溢出是C标准发明的人为废话。所有知名计算机在汇编程序级别进行溢出时都只是设置溢出和/或进位,由核心手册正确记录和明确定义。它在 C 语言中变成"未定义行为"的原因主要是因为 C 允许无意义的符号格式,如补码或有符号大小,其中可能有填充位、陷阱表示或其他此类异国情调的、主要是虚构的东西。

尽管如今,优化编译器利用不允许发生的溢出来生成更高效的代码。这是不幸的,因为如果 2 的补码是唯一允许的格式,我们本可以同时拥有快速和 100% 确定性代码。

最新更新