有符号整数加法,需要澄清

Gen*_*ene 1 c math binary

我有以下有符号整数:

(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那么你完全受编译器的支配.


San*_*nen 5

如果你使用的系统中的int是4位长,那么结果确实会溢出,结果将是-3.但是在C ints中至少是16位,因此结果将是13.