私が書いたいくつかの C コードでバグが発生しました。修正は比較的簡単でしたが、その根底にある問題をよりよく理解したいと考えています。基本的に何が起こったのかというと、2 つの符号なし整数 (実際には uint32_t) があり、モジュラス演算が適用されたときに、負の数に相当する符号なしの数値、つまりラップされたために「大きい」数値が得られました。以下は、デモ用のプログラム例です。
#include <stdio.h>
#include <stdint.h>
int main(int argc, char* argv[]) {
uint32_t foo = -1;
uint32_t u = 2048;
uint64_t ul = 2048;
fprintf(stderr, "%d\n", foo);
fprintf(stderr, "%u\n", foo);
fprintf(stderr, "%lu\n", ((foo * 2600000000) % u));
fprintf(stderr, "%ld\n", ((foo * 2600000000) % u));
fprintf(stderr, "%lu\n", ((foo * 2600000000) % ul));
fprintf(stderr, "%lu\n", foo % ul);
return 0;
}
これにより、x86_64 マシンで次の出力が生成されます。
-1
4294967295
18446744073709551104
-512
1536
2047
1536 は私が期待していた数値ですが、(uint32_t)(-512) は私が取得していた数値です。
だから、私の質問はこれだと思います: この場合、2 つの符号なし数値間のモジュラス演算は、除数よりも大きい数値 (つまり、負の数値) を生成するのはなぜですか? この動作が好まれる理由はありますか?