encontré un error en algún código c que escribí, y si bien fue relativamente fácil de corregir, quiero ser capaz de comprender mejor el problema subyacente. esencialmente, lo que sucedió es que tenía dos enteros sin signo (uint32_t, de hecho) que, cuando se aplicaba la operación del módulo, producía el equivalente sin signo de un número negativo, un número que se había envuelto y que por lo tanto era "grande". aquí es un programa de ejemplo para demostrar:desbordamiento sin signo con operador de módulo en 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;
}
esto produce la siguiente salida, en mi máquina x86_64:
-1
4294967295
18446744073709551104
-512
1536
2047
1536 es el número que estaba esperando, pero (uint32_t) (- 512) es el número que obtenía, que, como se puede imaginar, arrojó un poco las cosas.
lo tanto, supongo que mi pregunta es la siguiente: ¿por qué una operación módulo entre dos números sin signo, en este caso, producir un número que es mayor que el divisor (es decir, un número negativo)? ¿Hay alguna razón por la cual se prefiere este comportamiento?
2600000000 es un int (o tal vez un int de 64 bits, largo o largo), que puede haber causado que el resultado de la multiplicación se convierta en un (firmado) de largo. ¿En qué plataforma estás? – Random832