C 中的字符乘法
Char multiplication in C
我有这样的代码:
#include <stdio.h>
int main()
{
char a=20,b=30;
char c=a*b;
printf("%c\n",c);
return 0;
}
这个程序的输出是X .
如果 a*b=600 由于 char 值介于 -128 和 127 之间而溢出,这个输出怎么可能?
首先,这里的行为是实现定义的。一个 char
可能是 unsigned char
或 signed char
,因此它可能能够保持 0
到 255
或 -128
到 127
, 假设 CHAR_BIT == 8
.
600
的十进制为 0x258
。发生的事情是存储最低有效的八位,值为 0x58
a.k.a。 X
在 ASCII 中。
首先,看起来您的 unsigned char
范围从 0 到 255。
关于溢出,你是对的。
600 - 256 - 256 = 88
这只是'X'的ASCII码。
char
是有符号的还是无符号的由实现定义。无论哪种方式,它都是一个整数类型。
无论如何,由于integer promotions,乘法按int
完成,结果转换为char
。
如果该值不适合 "smaller" 类型,它是为 signed char
定义的实现方式。大多数(如果不是全部)实现只是简单地切断了高位。
对于 unsigned char
,标准实际上要求(简要地)切割高位。
所以:
(int)20 * (int)20 -> (int)600 -> (char)(600 % 256) -> 88 == 'X'
(假设 8 位char
)。
有关详细信息,请参阅 link 及其周围的段落。
注意:如果您启用编译器警告(一如既往的建议),您应该会收到一个赋值的截断警告。这可以通过显式强制转换来避免(仅当您 确实 确定所有含义时)。 gcc 选项是 -Wconversion
.
如果 char
已签名,此代码将导致未定义的行为。
我认为有符号整数溢出是未定义的行为,但转换为更小的类型是实现定义的。
引自N1256 6.3.1.3 有符号和无符号整数:
3 Otherwise, the new type is signed and the value cannot be represented in it; either the
result is implementation-defined or an implementation-defined signal is raised.
如果该值被简单地截断为 8 位,则 (20 * 30) & 0xff == 0x58
和 0x58 是 X
的 ASCII 码。因此,如果您的系统执行此操作并使用 ASCII 代码,则输出将为 X.
我有这样的代码:
#include <stdio.h>
int main()
{
char a=20,b=30;
char c=a*b;
printf("%c\n",c);
return 0;
}
这个程序的输出是X .
如果 a*b=600 由于 char 值介于 -128 和 127 之间而溢出,这个输出怎么可能?
首先,这里的行为是实现定义的。一个 char
可能是 unsigned char
或 signed char
,因此它可能能够保持 0
到 255
或 -128
到 127
, 假设 CHAR_BIT == 8
.
600
的十进制为 0x258
。发生的事情是存储最低有效的八位,值为 0x58
a.k.a。 X
在 ASCII 中。
首先,看起来您的 unsigned char
范围从 0 到 255。
关于溢出,你是对的。
600 - 256 - 256 = 88
这只是'X'的ASCII码。
char
是有符号的还是无符号的由实现定义。无论哪种方式,它都是一个整数类型。
无论如何,由于integer promotions,乘法按int
完成,结果转换为char
。
如果该值不适合 "smaller" 类型,它是为 signed char
定义的实现方式。大多数(如果不是全部)实现只是简单地切断了高位。
对于 unsigned char
,标准实际上要求(简要地)切割高位。
所以:
(int)20 * (int)20 -> (int)600 -> (char)(600 % 256) -> 88 == 'X'
(假设 8 位char
)。
有关详细信息,请参阅 link 及其周围的段落。
注意:如果您启用编译器警告(一如既往的建议),您应该会收到一个赋值的截断警告。这可以通过显式强制转换来避免(仅当您 确实 确定所有含义时)。 gcc 选项是 -Wconversion
.
如果 char
已签名,此代码将导致未定义的行为。
我认为有符号整数溢出是未定义的行为,但转换为更小的类型是实现定义的。
引自N1256 6.3.1.3 有符号和无符号整数:
3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
如果该值被简单地截断为 8 位,则 (20 * 30) & 0xff == 0x58
和 0x58 是 X
的 ASCII 码。因此,如果您的系统执行此操作并使用 ASCII 代码,则输出将为 X.