带负红利和除数的C模运算差是长无符号的
嗨,我知道在带负红利和除数的C模运算差是长无符号的,c,modulo,C,Modulo,嗨,我知道在C中,负除数的模会产生负模,但我发现,使用长无符号除数或长无符号除数的负除数的模会产生正模 下面是一个例子: #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
C
中,负除数的模
会产生负模,但我发现,使用长无符号除数或长无符号除数的负除数的模会产生正模
下面是一个例子:
#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;
}
有人能解释为什么吗?我已经在GCC 4.8和5.1中尝试过了,C99第6.5.5/6节要求当a/b可表示时: (a/b)*b+a%b应等于a 从6.5.5/3开始 通常的算术转换是在操作数上执行的 有关算术转换的更多详细信息,请参阅第6.3.1.8节 现在,它似乎出现在您的实现中
sizeof(long)=sizeof(long-long)=64位
对于前4种情况,有符号或无符号除数可以更改为分子类型(即long long int
),但在后2种情况下,必须将除数更改为无符号类型(强制转换或重新解释为),因为除数具有相同的宽度且无符号导致结果
在某些系统上,如果sizeof(long)
,则倒数第二个结果应该不同。不存在使用一个有符号和一个无符号操作数执行的(内置)算术运算;二元运算的两个操作数升级为同一类型
在最后两个示例中,该类型为无符号long-long
;因此,a
被转换成一个无符号值,余数是用它来计算的。“负红利的模导致负模”是错误的。这是实现定义的。@n.m。。。在早期的C标准中。我也知道在C11之前的标准中,带负号的模是特定于实现的,但无论如何,我也对实现的原理感兴趣,我在当前的标准中找不到任何解释这种行为的东西。请看这个线程@DevSolar N1570 6.5.5.6:"... 如果商a/b是可表示的,则表达式(a/b)*b+a%b应等于a;否则,a/b和a%b的行为都未定义。“
$> ./a.out
-4 -4 -4 -4 12 12