2012-02-05 22 views
17

Para una implementación que incluye f0 y f1 en el mismo byte, ¿se define el programa a continuación?Campos de bits y puntos de secuencia

struct S0 { 
     unsigned f0:4; 
     signed f1:4; 
} l_62; 

int main (void) { 
     (l_62.f0 = 0) + (l_62.f1 = 0); 
     return 0; 
} 

Estoy interesado en la respuesta para C99 y C11 de si hay razones para pensar que es diferente allí.

En C99, todo lo que encontré fue 6,5: 2:

Entre el anterior y el siguiente punto de la secuencia de un objeto tendrá su valor almacenado modi fi ed como máximo una vez por la evaluación de una expresión. [...]

No tengo claro qué consecuencias tiene este párrafo en el programa anterior.

Según la gran cantidad de pruebas aleatorias, la mayoría de los compiladores parecen generar código donde las dos asignaciones no interfieren.

+1

Esas partes de las normas me dan dolores de cabeza. Mi lectura actual es que la intención es que sea UB (por ejemplo, está claro en C11 que la modificación de los dos campos en dos subprocesos es un curso no sincronizado), pero el lenguaje en 6.5 se olvida de mencionar el campo de bits como en otro lugares donde los campos de bits tienen un manejo especial. – AProgrammer

+0

@AProgrammer: El código anterior tiene un significado lógico claro (trate las escrituras como si ocurrieran secuencialmente, en cualquier orden) y no hay ninguna razón por la cual un compilador cuyo autor no sea obtuso no genere código que produzca ese comportamiento en el caso de un hilo. ¿Puede sugerir alguna razón plausible por la cual los autores del Estándar podrían haber tenido la intención de que sea UB? – supercat

Respuesta

3

C11 considera adyacentes llamados campos de bits para formar parte de la misma ubicación de memoria. No se garantiza que estos campos de bit sean actualizados atómicamente, en otras palabras, si una actualización no está secuenciada explícitamente antes que la otra, el comportamiento no está definido. 3.14 memory location luego también tiene una explicación detallada de cuándo se pueden considerar dos campos en diferentes ubicaciones de memoria, por lo que las actualizaciones se pueden considerar de forma independiente.

Si desea modificar su estructura

struct S0 { 
     unsigned f0:4; 
     int :0; 
     signed f1:4; 
} l_62; 

tal que existe este extraño "separador de posición de memoria" entre los campos de dos bits, el código se garantizaría a estar bien.

Para C99 el caso parece ser más complicado, no existe un concepto tan detallado de la ubicación de la memoria. En una discusión reciente sobre la lista de correo del kernel de Linux, se afirmaba que, en general, para todos los pares de campos de bits habría una garantía de atomicidad al actualizar cualquiera de ellos. El punto de partida de esa discusión fue un caso en el que gcc contaminó un campo que no era de bit que colindaba con un campo de bit de una manera inesperada, lo que provocó fallos espurios.

+2

La modificación de la misma ubicación de memoria es una carrera de datos en C11, eso es seguro. Pero mientras 5.1.2.4/4 habla de la ubicación de la memoria, 6.5/2 solo habla de objetos escalares. Y no estoy seguro de que sea un descuido. Las expresiones correspondientes en C++ son similares, raza de datos, pero aparentemente no UB para una sola expresión en un solo hilo. – AProgrammer

+0

@AProgrammer: Sería muy poco práctico en la mayoría de las plataformas exigir que las escrituras simultáneas (diferentes hilos) en diferentes campos de bits en el mismo elemento de almacenamiento se comporten de manera secuencialmente consistente. La mayoría de las plataformas podrían, por un costo prácticamente nulo, garantizar que las escrituras de un campo no afectarán las lecturas simultáneas de otro, pero como eso no sería gratuito en todas las plataformas, el Estándar no lo exige. Sin embargo, no veo nada que sugiera que no se debe esperar que los compiladores manejen casos de subprocesos únicos. – supercat

0

La tarea aquí es para los miembros de la estructura. El hecho de que compartan el mismo almacenamiento no debería tener ningún efecto en la lógica. De hecho, no has hecho una asignación a la misma cosa.

Por supuesto, no soy un abogado de idiomas.

Cuestiones relacionadas