例如,假设您有以下变量:
int i = 9;
int j = 7;
Run Code Online (Sandbox Code Playgroud)
根据实现,,,的值(-i)/j可以是–1或–2.怎么可能得到这两个不同的结果?
令人惊讶的是,结果是C89中定义的实现:
ANSI草案 §3.3.5
当整数被划分并且除法不精确时,如果两个操作数都是正数,则/运算符的结果是小于代数商的最大整数,并且%运算符的结果是正数. 如果任一操作数为负,则/运算符的结果是小于代数商的最大整数还是大于代数商的最小整数是实现定义的
然而,这在C99中有所改变
N1256§6.5.5 / 6
当整数被划分时,/运算符的结果是代数商,丢弃任何小数部分*
用脚注:
*这通常被称为"截断为零"
澄清一下,"实现定义"意味着实现必须决定哪一个,它并不意味着有时你会得到一个东西,有时你会得到另一个(除非实现定义它做一些非常奇怪的东西,我猜).
在 C89 中,对于负操作数,除法结果/可以以任意方式截断。(在 C99 中,结果将被截断为零。)
历史原因在 C99 Rationale 中有解释:
\n\n\n国际标准的基本原理 \xe2\x80\x94 编程语言 \xe2\x80\x94 C \xc2\xa76.5.5 乘法运算符
\n在 C89 中,涉及负操作数的整数除法可以以实现定义的方式向上或向下舍入;目的是避免在运行时代码中产生开销来检查特殊情况并强制执行特定行为。然而,在 Fortran 中,结果总是会截断为零,并且开销对于数字编程社区来说似乎是可以接受的。因此,C99 现在需要类似的行为,这应该有助于将代码从 Fortran 移植到 C。
\n