您好我知道C
负股息的modulo
导致负模数,但我发现使用长无符号除数的负股息模数或者一个很长的无符号除数会产生正模数!
以下是一个例子:
#include <stdio.h>
int main(int argc, char** argv)
{
long long int a = -2205348223670655684LL;
printf("%lld %lld %lld %lld %lld %lld\n", a % 20, a % 20L, a % 20LL, a % 20U, a % 20LU, a % 20LLU);
return 0;
}
和输出:
$> ./a.out -4 -4 -4 -4 12 12
任何人都可以解释原因吗?我已经尝试过GCC 4.8和5.1
答案 0 :(得分:4)
C99第6.5.5 / 6节要求当a / b可表示时:
(a / b)* b + a%b应等于
从6.5.5 / 3
通常的算术转换是在操作数上执行的。
有关算术转换的更多详细信息,请参阅第6.3.1.8节。
现在看来你的实施sizeof(long) = sizeof(long long) = 64 bits
对于前4个案例,有符号或无符号除数可以更改为分子类型(即long long int
),但在最后2个案例中,除数必须更改(转换或重新解释为)为无符号类型,因为除数有相同的宽度和无符号导致结果。
在sizeof(long) < sizoef(long long)
的某些系统上,第二个结果应该不同。
答案 1 :(得分:3)
没有使用一个有符号和一个无符号操作数执行的(内置)算术运算;二进制操作的两个操作数都被提升为相同的类型。
在最后两个示例中,该类型为unsigned long long
;所以a
转换为无符号值,余数用它计算。