在C语言中,整数运算的中间结果使用哪种精度?
假设我有以下变量和以下等式:在C语言中,整数运算的中间结果使用哪种精度?,c,typedef,C,Typedef,假设我有以下变量和以下等式: int16_t a,b,c,d; int32_t result; result = a*b - c*d; ab和cd的中间结果将存储在16位还是32位 PS:我可以比写问题更快地测试这个问题,我想知道C规范说了什么。中间结果将是int类型 任何小于int的类型都将首先升级。这些整数提升是针对类型int或unsigned**。因此,数学运算必须发生在int、unsigned或原始类型 int16\t当然更窄,或者与int相同 结果的类型与中间结果的类型无关 int
int16_t a,b,c,d;
int32_t result;
result = a*b - c*d;
ab和cd的中间结果将存储在16位还是32位
PS:我可以比写问题更快地测试这个问题,我想知道C规范说了什么。中间结果将是
int
类型
任何小于int
的类型都将首先升级。这些整数提升是针对类型int
或unsigned
**。因此,数学运算必须发生在int
、unsigned
或原始类型
int16\t
当然更窄,或者与int
相同
结果的类型
与中间结果的类型无关
int16_t a,b,c,d;
int32_t result = a*b - c*d;
要使所有平台都具有可移植性,包括int
窄于int32\t
的平台,请确保使用至少32位数学计算产品
#include <stdint.h>
int32_t result = INT32_C(1)*a*b - INT32_C(1)*c*d;
#包括
int32_t result=int32_C(1)*a*b-int32_C(1)*C*d;
当然,结果存储为32位,可能是扩展中间结果的符号 对于具有32位或64位
int
的机器,中间结果将适合int32\u t
,值没有任何变化,没有例外。结果为-2147450880至2147450880
(80008000至7FFF8000)
**永远不要长,即使在平台上也不要长。我很快就会更新这个答案。我不再相信该标准允许将int16\t
提升为long
。但是,在一些非常模糊的情况下,它可以升级为unsigned int
。整数转换秩规则对于外来系统有一些奇怪的结果。
这几乎是正确的。有两种模糊且不太可能的情况,中间结果的类型为long int
int16\u t
必须是不带填充位的16位2的补码整数类型。int16\u t
类型的操作数将升级为可以表示int16\u t
类型的所有可能值的类型,并且其宽度至少与int
相同
标准要求int
的范围至少为-32767到+32767
假设int
使用1的补码或符号和幅度表示,或者使用2的补码表示,但通常为-32768
的表示被视为陷阱表示。然后,int
不能保存类型为int16\u t
的所有值,必须将操作数提升为long
(这保证具有足够宽的范围)
要实现这一点,该实现必须同时支持具有受限16位范围的int
类型(很可能不是2的补码)和适合int16\t
的类型,这意味着它具有2的补码表示,并且没有填充位或陷阱表示。例如,1的补码系统更可能没有这种类型,因此它根本不会定义int16\t
(尽管它会定义int\u fast16\t
和int\u least16\t
)
对于几乎所有的实际实现,int
可以保存int16\u t
类型的所有值,因此中间结果是int
类型的。对于几乎所有剩余的真实世界或假设系统,int16\t
。对于假设的一小部分不存在但符合条件的C实现,中间结果的类型为long int
更新:chux指出了我论点中可能存在的弱点。在一篇评论中,他认为6.2.6.2第2段说,整数类型可以使用两个补码、一个补码或符号和大小来表示,其目的是要求所有整数类型使用相同的表示(当然,位数不同,但都使用相同的选项)
J.3.5中非规范性文本的措辞,表示:
是否使用符号和大小表示有符号整数类型,
二补,还是一补,是否超常
值是陷阱表示或普通值
是实现定义的,在解释中倾向于支持这一点。如果不同的整数类型在这方面可能有所不同,那么对于每个整数类型都应该这样说
然而:
int16\t
等的代码,实现可能在软件中支持2的补码整数,或者硬件可能直接支持这两种表示。(我猜想作者没有考虑这种可能性,但我们只能按照标准实际所说的去做。)
int16\u t
提升为long int
- 所有整数类型都使用2的补码表示
INT_MAX==+32767
INT\u MIN==-32767
- 带有符号位1和所有值位0的
是陷阱表示int
int
没有填充位,但通常表示-32768
的位模式是陷阱表示。N1570 6.2.6.2第2段明确允许这样做
但是int16\t