que - ¿Por qué una operación de módulo está devolviendo un valor inesperado?
module operator in c (3)
¿Por qué se imprime el siguiente código 255 ?
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint8_t i = 0;
i = (i - 1) % 16;
printf("i: %d/n", i);
return 0;
}
Asumí 15 , aunque i - 1 evalúa como un entero.
Debido a las promociones enteras en el estándar C. Brevemente: cualquier tipo "más pequeño" que int se convierte a int antes de su uso. No puedes evitar esto en general.
Entonces, qué pasa: i es promovido a int . La expresión se evalúa como int (las constantes que utiliza también son int ). El módulo es -1 . Esto luego se convierte a uint8_t : 255 por la asignación.
Para printf entonces i se promueve en enteros a int (de nuevo): (int)255 . Sin embargo, esto no hace daño.
Tenga en cuenta que en C89, para a < 0 , a % b no es necesariamente negativo. Estaba definido por la implementación y podría haber sido 15 . Sin embargo, dado que C99, se garantiza que -1 % 16 sea -1 ya que la división debe producir el cociente algebraico .
Si desea asegurarse de que el módulo dé un resultado positivo, debe evaluar la expresión completa unsigned al lanzar i :
i = ((unsigned)i - 1) % 16;
Recomendación: Habilitar las advertencias del compilador. Al menos la conversión para la asignación debe dar una advertencia de truncamiento.
Esto funciona (muestra 15) con el compilador de Microsoft C (sin stdint.h, así que usé typedef):
#include <stdio.h>
typedef unsigned char uint8_t;
int main(void) {
uint8_t i = 0;
i = (uint8_t)(i - 1) % 16;
printf("i: %d/n", i);
return 0;
}
La razón para el 255 es porque (i - 1) se promueve a entero, y la división entera utilizada para% en C redondea hacia cero en lugar de infinito negativo (redondear hacia infinito negativo es la forma en que se hace en matemáticas, ciencias y otros) lenguajes de programación). Entonces, para C% es cero o tiene el mismo signo que el dividendo (en este caso -1% 16 == -1), mientras que en matemáticas el módulo es cero o tiene el mismo signo que el divisor.
Esto se debe a que -1 % n devolvería -1 y NO n - 1 1 . Como i en este caso no tiene signo de 8 bits int, se convierte en 255.
1 1 sobre cómo funciona el módulo para enteros negativos en C / C ++.