我可以依赖C中的%(modulo)运算符来表示负数吗?

时间:2015-03-21 04:45:42

标签: c rounding modulo behavior floor-division

使用GCC:

printf("%i \n", -1 % (int)4);
printf("%u \n", -1 % (unsigned int)4);

输出:

-1
3

我可以跨平台依赖此行为吗?我应该明确定义MODREM宏以确保不会更改吗?

3 个答案:

答案 0 :(得分:4)

从C99起,%的结果需要舍入为0 ,如Chris Dodd所引用。

在C99标准之前,%运算符在负数上的行为是实现定义

  

当整数被划分且除法不精确时,如果两个操作数均为正,则/运算符的结果是小于代数商的最大整数,%运算符的结果为正。 如果任一操作数为负/运算符的结果是小于代数商的最大整数还是大于代数商的最小整数实现定义的< / strong>,这是%运算符结果的符号。如果商a/b可表示,则表达式(a/b)*b + a%b应等于a

     

Does either ANSI C or ISO C specify what -5 % 10 should be?

如果您定位C99或更新版本,结果是,否则您无法依赖它。

如果您需要一致的结果与可移植性甚至更旧的C标准,您可以使用div or ldiv,无需定义自己的MODREM

C99 rationale regarding div, ldiv, and lldiv functions

  

因为当涉及负操作数时,C89具有用于划分有符号整数的实现定义语义,所以发明了C99中的div和ldiv以及lldiv,以便为有符号整数除法和余数运算提供明确指定的语义。

答案 1 :(得分:1)

C99标准说:

  

6.5.5乘法运算符

  

当整数被分割时, / 运算符的结果是任何代数商   分数部分丢弃 87)。如果商 a / b 可表示,则表达式为   (a / b)* b + a%b 应等于 a

  

87)这通常被称为''截断为零''

这意味着鸿沟总是向0舍入,所以你可以依赖它。

请注意,这与C ++ 03标准不同。

你的第二行是无符号除法,在除法之前将值-1转换为unsigned int。这总是小于2的幂,因此也很明确。

答案 2 :(得分:-3)

模运算符(%)多年来一直是C和C ++标准的一部分。我不确定你可以在C ++中重载它。所以,你可以依靠它。