今天我发现了以下内容:
#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),那么我会得到类似的行为。通常建议不要对不同大小的操作数进行算术运算吗?
答案 0 :(得分:11)
char
可以是有符号或无符号的,具体取决于您的编译器。
在您的情况下,它似乎是有符号的,并且255超出了它可以代表的范围(可能,它只能代表-128到127之间的数字)。
因此,当您为char
变量分配255时会出现问题 - 这会导致实现定义的值,在您的情况下,似乎为-1。
当你将-1乘以2时,得到-2。那里没有神秘感。对(int)
的强制转换不执行任何操作 - 比int
更窄的类型在使用它们进行任何计算之前始终会提升为int
或unsigned int
。
答案 1 :(得分:5)
似乎在您的平台上签署了char。因此char x = 255
实际上与char x = -1
相同。强制转换为int并不重要。
尝试将其更改为:
unsigned char x = 255;
答案 2 :(得分:4)
不,你没有在第二行(乘法)上溢出。问题是你的编译器默认使用signed char
并且255溢出并且意味着-1。基本上,您使用值-1初始化变量x
。将-1转换为int将导致-1(signed
操作数将在upcast中进行符号扩展,而unsigned
操作数将得到零扩展。
您可以通过添加char
前缀强制unsigned
为unsigned
:
unsigned char x = 255;
答案 3 :(得分:3)
其他答案很好地解释了你的例子如何“有效”,所以我不再解释。
但是,让我观察一下,如果你想要使用的是“无符号8位整数”,那么只需使用<stdint.h>
的{{1}}(和它的16,32,64位同伴)和远离这个世界上的所有uint8_t
,char
和short
。