6

今天我发现了以下内容:

#include <stdio.h>

int main(){
char x = 255;
int z = ((int)x)*2;

printf("%d\n", z); //prints -2

return 0;

}

所以基本上我得到了溢出,因为大小限制是由 = 符号右侧的操作数决定的?

为什么在乘法之前不将其转换为 int ?

在这种情况下,我使用的是 char 和 int,但如果我使用“long”和“long long int”(c99),那么我会得到类似的行为。通常建议不要使用不同大小的操作数进行算术运算吗?

4

4 回答 4

11

char可以是有符号的或无符号的,具体取决于您的编译器。

在您的情况下,它似乎已签名,并且 255 超出了它可以表示的范围(可能只能表示从 -128 到 127 的数字)。

因此,当您将 255 分配给char变量时,就会出现问题 - 这会导致实现定义的值,在您的情况下,它似乎是 -1。

当你将 -1 乘以 2 时,你得到 -2。那里没有奥秘。强制转换(int)什么都不做 - 类型比int总是提升到intunsigned int在使用它们完成任何计算之前更窄。

于 2010-04-16T00:09:21.753 回答
5

看来 char 已在您的平台上签名。所以char x = 255实际上与 相同char x = -1。转换为 int 无关紧要。

尝试将其更改为:

unsigned char x = 255;
于 2010-04-16T00:08:23.610 回答
4

不,第二行(乘法)没有溢出。问题是您的编译器signed char默认使用并且 255 溢出并且意味着 -1。基本上,您正在x使用 -1 的值初始化变量。将 -1 转换为 int 将导致 -1 (signed操作数将在向上转换中进行符号扩展,而unsigned操作数将进行零扩展)。

char您可以unsigned通过添加unsigned前缀来强制成为:

unsigned char x = 255;
于 2010-04-16T00:08:11.847 回答
3

其他答案很好地解释了您的示例如何“工作”,所以我不会再解释了。

但是,让我观察一下,如果您要使用的是“无符号 8 位整数”,只需使用<stdint.h>'s uint8_t(及其 16、32、64 位同伴)并远离这个世界上的所有chars、shorts 和s int.

于 2010-04-16T00:33:20.967 回答