例如,这些表达式的值是多少?它们是否依赖于编译器?
-7/3 -7%3
7/-3 7%-3
-7/-3 -7%-3
在 C89 中,/
对于负操作数,除法的结果可以被截断。
在 C99 或更高版本中,结果将被截断为零。
%
操作员依赖/
于所有标准的行为。
参考:
C89 § 3.3.5
如果任一操作数为负,则
/
运算符的结果是小于或等于代数商的最大整数还是大于或等于代数商的最小整数是实现定义的,结果的符号也是%
操作员。如果商a/b
是可表示的。表达式(a/b) * b + a%b
应等于a
。
和
C11 § 6.5.5
当整数被除法时,
/
运算符的结果是任何小数部分被丢弃的代数商
带脚注:
这通常被称为“向零截断”
由于 % 取决于 / (它们实际上是相同的操作, / 返回商,而 % 返回余数。)那么你得到的就是基于提供的操作数。C 遵循代数规则,所以以下是正确的:
结果将取决于您的编译器遵循的语言规范。运算符/
和%
通过以下关系相互联系
(a / b) * b + (a % b) == a
标准 C89/90 表示除法的结果是实现定义的:允许编译器实现欧几里得除法(截断向负无穷大,非负余数)或 Fortran 风格的除法(截断向零,可能为负余数)。
在欧几里得除法
-7/3 = -3 -7%3 = 2
7/-3 = -2 7%-3 = 1
-7/-3 = 3 -7%-3 = 2
在 Fortran 风格的除法中
-7/3 = -2 -7%3 = -1
7/-3 = -2 7%-3 = 1
-7/-3 = 2 -7%-3 = -1
标准 C99(及更高版本)要求所有 C 编译器实现 Fortran 风格的除法。
旁注:C++ 一直坚持到 C++03 的实现定义规范。不过,C++11 要求使用 Fortran 风格的除法。