我有以下有符号整数:
(4bits)a = 6;
(4bits)b = 7;
(4bits)c;
c = a + b;
Run Code Online (Sandbox Code Playgroud)
c = 13或c = -3?如果我做二进制数学并假设它是一个4位数:0110 + 0111 = 1101(-8 + 4 + 0 + 1)= -3
Ste*_*sop 10
与流行的看法相反,C 确实有4位整数类型.但是,它没有这些类型的对象,只有位字段(6.7.2.1/9,"位字段被解释为由指定位数组成的有符号或无符号整数类型"):
#include <stdio.h>
typedef struct int4bit {
signed int value:4;
} int4bit;
int main() {
int4bit a, b, c;
a.value = 6;
b.value = 7;
c.value = a.value + b.value;
printf("%d\n", c.value);
}
Run Code Online (Sandbox Code Playgroud)
该程序与我的编译器的输出是-3
,但标准不保证这一点.原因是表达式a.value + b.value
具有类型int
(因为整数提升规则,6.3.1.1/2)和值13.值13不能用4位有符号整数表示,因此发生以下两种情况之一:要么是实现 - 定义结果或实现定义信号(6.3.1.3/3).
简而言之,您所能做的就是检查编译器文档,或运行代码并查看它的作用.但是这个结果-3对于带有符号整数类型的2s补码表示的实现来说非常自然.
该值不能为13,因为13不在4位有符号整数可表示的值范围内.只要实现在没有溢出检查的1s补码机器上记录它,例如它自然可以是-2,任何东西都是允许的.不是说你可能遇到过这样的机器......
这是一种特殊情况,因为获得4位整数类型的唯一方法是作为位字段.通常,有符号整数运算的溢出是未定义的行为(6.5/5,"结果是......不在其类型的可表示值的范围内").由于促销,您的示例中没有算术溢出int
,因此实现可用的行为范围有限 - 不允许格式化硬盘.但如果你确实溢出了,int
那么你完全受编译器的支配.