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 ++.