tipo error desbordamiento datos convertir aritmético aritmetico c overflow modulo integer-arithmetic

error - desbordamiento aritmetico sql server



¿Es el desbordamiento aritmético equivalente a la operación de módulo? (7)

Esto debería funcionar bien porque solo debería volver a 0. Como se señaló en un comentario sobre una respuesta diferente, solo debe hacerlo cuando el valor no esté firmado, ya que puede tener un comportamiento indefinido con un valor firmado.

Sin embargo, es probable que sea mejor dejar esto usando el módulo, ya que el código será comprendido por otras personas que mantienen el código, y un compilador inteligente puede estar haciendo esta optimización de todos modos, lo que puede hacer que sea inútil en primer lugar. Además, la diferencia de rendimiento probablemente será tan pequeña que no importaría en primer lugar.

Necesito hacer aritmética modulo 256 en C. Así que simplemente puedo hacer

unsigned char i; i++;

en lugar de

int i; i=(i+1)%256;


Funcionará si el número de bits que está utilizando para representar el número es igual al número de bits en la representación binaria (sin signo) (100000000) del divisor -1, que en este caso es: 9-1 = 8 (char)


Hay otra alternativa que no se ha mencionado, si no desea utilizar otro tipo de datos.

unsigned int i; // ... i = (i+1) & 0xFF; // 0xFF == 255

Esto funciona porque el elemento de módulo == 2^n , lo que significa que el rango será [0, 2^n-1] y, por lo tanto, una máscara de bits mantendrá el valor fácilmente dentro del rango deseado. Es posible que este método no sea mucho o menos eficiente que la versión unsigned char / uint8_t , dependiendo de la magia que haga su compilador entre bambalinas y de cómo el sistema de destino maneja cargas sin palabras (por ejemplo, algunas arquitecturas RISC requieren Operaciones adicionales para cargar valores que no sean de tamaño de palabra). Esto también supone que su compilador no detectará el uso de la aritmética de módulo de potencia de dos en valores sin signo y lo sustituirá por una máscara de bits para usted, por supuesto, como en los casos en que el uso de módulo tendría un mayor valor semántico como la base de su decisión no es exactamente portátil, por supuesto).

Una ventaja de este método es que puede usarlo para potencias de dos que no son también del tamaño de un tipo de datos, por ejemplo,

i = (i+1) & 0x1FF; // i %= 512 i = (i+1) & 0x3FF; // i %= 1024 // etc.


No. No hay nada que garantice que los caracteres unsigned char tengan ocho bits. Use uint8_t de <stdint.h> , y estará perfectamente bien. Esto requiere una implementación que admita stdint.h : cualquier compilador compatible con C99 sí lo hace, pero los compiladores más antiguos pueden no proporcionarlo.

Nota: la aritmética no firmada nunca se desborda y se comporta como "módulo 2 ^ n". Aritmética firmada desborda con comportamiento indefinido.


Probablemente sí, pero las razones para ello en este caso son bastante complicadas.

unsigned char i = 255; i++;

El i++ es equivalente a i = i + 1 .

(Bueno, casi. i++ produce el valor de i antes de que se incrementara, por lo que es realmente equivalente a (tmp=i; i = i + 1; tmp) `. Pero como el resultado se descarta en este caso, no es así. plantear cualquier problema adicional.)

Dado que el unsigned char es un tipo estrecho, un operando unsigned char para el operador + se promueve a int (asumiendo que int puede contener todos los valores posibles en el rango de los caracteres unsigned char ). Entonces, si i == 255 , y UCHAR_MAX == 255 , entonces el resultado de la adición es 256 , y es de tipo (firmado) int .

La asignación convierte implícitamente el valor 256 de int back a unsigned char . La conversión a un tipo sin signo está bien definida; el resultado se reduce a módulo MAX+1 , donde MAX es el valor máximo del tipo sin signo de destino.

Si i fuera declarado como un unsigned int :

unsigned int i = UINT_MAX; i++;

no habría conversión de tipo, pero la semántica del operador + para tipos sin signo también especifica el módulo de reducción MAX+1 .

Tenga en cuenta que el valor asignado a i es matemáticamente equivalente a (i+1) % UCHAR_MAX . UCHAR_MAX suele ser de 255 , y se garantiza que sea de al menos 255 , pero legalmente puede ser más grande.

Podría haber un sistema exótico en el que UCHAR_MAX también se almacene en un objeto int firmado. Esto requeriría UCHAR_MAX > INT_MAX , lo que significa que el sistema debería tener al menos bytes de 16 bits. En tal sistema, la promoción sería desde unsigned char a unsigned int . El resultado final sería el mismo. No es probable que encuentres un sistema así. Creo que hay implementaciones de C para algunos DSPs que tienen bytes mayores de 8 bits. El número de bits en un byte se especifica mediante CHAR_BIT , definido en <limits.h> .

CHAR_BIT > 8 no implica necesariamente UCHAR_MAX > INT_MAX . Por ejemplo, podría tener CHAR_BIT == 16 y sizeof (int) == 2 , es decir, bytes de 16 bits y int 32 bits).


Sí, el comportamiento de ambos ejemplos es el mismo. Ver C99 6.2.5 §9:

Un cálculo que involucre operandos sin signo nunca puede desbordarse, porque un resultado que no puede ser representado por el tipo entero sin signo resultante se reduce en módulo el número que es uno mayor que el valor más grande que puede ser representado por el tipo resultante.


unsigned char c = UCHAR_MAX; c++;

Básicamente sí, no hay desbordamiento, pero no porque c es de un tipo sin signo. Hay una promoción oculta de c a int aquí y una conversión entera de int a unsigned char y está perfectamente definida.

Por ejemplo,

signed char c = SCHAR_MAX; c++;

Tampoco es un comportamiento indefinido, porque en realidad es equivalente a:

c = (int) c + 1;

y la conversión de int a signed char se define aquí por la implementación (consulte c99, 6.3.1.3p3 sobre conversiones de enteros). Para simplificar se supone CHAR_BIT == 8 .

Para obtener más información sobre el ejemplo anterior, sugiero leer esta publicación:

"La pequeña función C del infierno"

http://blog.regehr.org/archives/482