使用 GCC:
printf("%i \n", -1 % (int)4);
printf("%u \n", -1 % (unsigned int)4);
输出:
-1
3
我可以跨平台依赖这种行为吗?我应该明确定义 MOD
和REM
宏以确保这不会被改变吗?
使用 GCC:
printf("%i \n", -1 % (int)4);
printf("%u \n", -1 % (unsigned int)4);
输出:
-1
3
我可以跨平台依赖这种行为吗?我应该明确定义 MOD
和REM
宏以确保这不会被改变吗?
从 C99 开始, Chris Dodd 引用的%
结果需要向 0 舍入。
在 C99 标准之前,%
运算符对负数的行为是实现定义的。
当整数被除且除法不精确时,如果两个操作数都是正数,则
/
运算符的结果是小于代数商的最大整数,并且%
运算符的结果是正数。 如果任一操作数为负数,则/
运算符的结果是小于代数商的最大整数还是大于代数商的最小整数是实现定义的,运算符结果的符号也是如此%
。如果商a/b
是可表示的,则表达式(a/b)*b + a%b
应等于a
。
因此,如果您的目标是 C99 或更高版本,则结果是肯定的,否则您不能依赖它。
如果您需要与旧 C 标准的可移植性一致的结果,您可以使用div
orldiv
,无需定义自己的MOD
和REM
C99 关于div
、ldiv
和lldiv
函数的基本原理:
因为当涉及负操作数时,C89 具有实现定义的有符号整数除法语义,所以发明了 div 和 ldiv 以及 C99 中的 lldiv 来为有符号整数除法和余数运算提供明确指定的语义。
C99 标准说:
6.5.5 乘法运算符
:
当整数被除法时,/运算符的结果是代数商,其中任何小数部分被丢弃87)。如果商a/b是可表示的,则表达式
(a/b)*b + a%b应等于a。
:
87) 这通常被称为“向零截断”</p>
这意味着除法总是向 0 舍入,所以你可以依赖它。
请注意,这与 C++03 标准不同。
您的第二行进行无符号除法,将值转换为-1
除法unsigned int
之前。这总是比 2 的幂小一,所以这也是很好定义的。
模运算符 ( %
) 多年来一直是 C 和 C++ 标准的一部分。我不确定您是否可以在 C++ 中重载它。所以是的,你可以依靠它。