débordement non signé avec opérateur de module en c
Question
J'ai rencontré un bogue dans un code C que j'ai écrit, et bien qu'il soit relativement facile à corriger, je veux être en mesure de mieux comprendre le problème qui le sous-tend. Essentiellement, ce qui s'est passé, c'est que j'ai eu deux entiers non signés (Uint32_T, en fait) que, lorsque l'opération de module a été appliquée, a donné l'équivalent non signé d'un nombre négatif, un nombre qui avait été enveloppé et était donc "grand". Voici un exemple de programme à démontrer:
#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;
}
Cela produit la sortie suivante, sur ma machine x86_64:
-1
4294967295
18446744073709551104
-512
1536
2047
1536 est le numéro que j'attendais, mais (uint32_t) (- 512) est le numéro que j'obtenais, ce qui, comme vous pouvez l'imaginer, a un peu jeté les choses.
Donc, je suppose que ma question est la suivante: pourquoi une opération de module entre deux nombres non signés, dans ce cas, produit-il un nombre supérieur au diviseur (c'est-à-dire un nombre négatif)? Y a-t-il une raison pour laquelle ce comportement est préféré?
Pas de solution correcte