私が書いた一部のCコードにバグがありましたが、修正するのは比較的簡単でしたが、より良い問題の原因を理解できるようにしたいと考えています。基本的に何が起こったのですか?モジュラス演算が適用されたときに、負の数の符号なし等価、ラップされた数が「大きい」という2つの符号なし整数(実際はuint32_t)があります。ここで実証するプログラム例です:Cのモジュラス演算子で符号なしオーバーフローが発生しました
#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つの符号なし数値の間のモジュラス演算は、なぜ除数(つまり負の数)より大きい数値を生成するのですか?この動作が好まれる理由はありますか?
2600000000はint型(int型long型またはlong型のlong型)なので、乗算の結果が(signed)longになる可能性があります。あなたはどんなプラットフォームですか? – Random832