2011-02-05 15 views
13

¿Puedo confiar en que el compilador C hace el módulo 2^n cada vez que accedo a un campo de bit? ¿O hay algún compilador/optimización en el que un código como el que se muestra a continuación no imprima Overflow?Desbordamiento en los campos de bit

struct { 
    uint8_t foo:2; 
} G; 

G.foo = 3; 
G.foo++; 

if(G.foo == 0) { 
    printf("Overflow\n"); 
} 

Gracias de antemano, Florian

+0

¿qué quieres decir? Le pidió explícitamente que almacene datos en dos bits. Además, 3 + 1 == 0 mod 4 –

+0

Me preocuparía más lo que le ocurra a ese bit si tiene declarados otros campos de bits en esa estructura. p.ej. uint8_t bar: 2; uint8_t foo: 2; uint8_t poo: 2; ¿afectaría la barra o la caca? – Dave

+0

¿Qué significa foo: 2? – CharlesB

Respuesta

11

Sí, puede confiar en que el compilador de C haga lo correcto aquí, siempre que el campo de bit se declare con un tipo sin signo, que tiene con uint8_t. De la norma C99 §6.2.6.1/3:

Los valores almacenados en campos de bit sin signo y objetos de tipo char sin signo se representarán utilizando una notación binaria pura. 40)

De §6.7.2.1/9:

Un campo de bits se interpreta como un tipo entero con o sin signo que consiste en el número especificado de bits. 104) Si el valor 0 o 1 se almacena en un campo de bits de ancho distinto de cero del tipo _Bool, el valor del campo de bits se comparará con el valor almacenado.

Y desde §6.2.5/9 (énfasis mío):

El rango de valores no negativos de un tipo entero con signo es un subrango del correspondiente tipo entero sin signo, y la representación de la el mismo valor en cada tipo es el mismo. 31)Un cómputo que involucre operandos sin firmar nunca puede desbordarse, porque un resultado que no puede ser representado por el tipo entero sin signo resultante es un módulo reducido que es mayor que el valor más grande que puede representar el tipo resultante.

Así que sí, puede estar seguro de que cualquier compilador normas conformes tendrá G.foo desbordamiento a 0 sin otros efectos secundarios no deseados.

+0

Como me señaló R ... en un comentario a continuación, el cálculo es en realidad un cálculo firmado. Eso no cambia la respuesta aquí, pero sería, digamos, con un campo de bits sin signo de 31 bits en una arquitectura donde las entradas son de 32 bits (donde podría haber un desbordamiento firmado indefinido). –

3

No. El compilador asigna 2 bits para el campo, e incrementando 3 resultados en 100b, que cuando se colocan en dos resultados bits en 0.

0

Respuesta corta : sí, puedes confiar en que el módulo 2^n suceda.

En su programa, G.foo++; es de hecho equivalente a G.foo = (unsigned int)G.foo + 1.

La aritmética int sin signo siempre produce 2^(tamaño de int sin signo en bits) resultados. Los dos bits de menor peso se almacenan en G.foo, produciendo cero.

+0

Su equivalencia es incorrecta. 'uint8_t' se promocionará a' int', not 'unsigned int'. 'G.foo ++;' es equivalente a 'G.foo = ((int) G.foo + 1)% 4; '. –

+0

@R .. Tienes razón (siempre obtengo estas promociones incorrectas), pero falta algo en la respuesta de Adam anterior, que es que el +1 se está produciendo realmente entre los inicios de sesión firmados. –

Cuestiones relacionadas