sirve que para fields estructuras estructura ejemplos datos campos arreglo anidadas c++ c enums bit-fields

c++ - que - ¿Es seguro usar una enumeración en un campo de bits?



estructuras en c++ pdf (4)

En C es un comportamiento no definido, porque un campo de bits solo puede haber signed int tipos signed int , int o unsigned int (o _Bool con C99).

6.5.2.1 :

Un campo de bits debe tener un tipo que sea una versión calificada o no calificada de uno de int, unsigned int, o sign firmado. Si la posición de bits de orden superior de un campo de bits int "sin formato" (posiblemente calificado) se trata como un bit de signo se define por implementación. Un campo de bits se interpreta como un tipo integral que consiste en el número especificado de bits.

De lo contrario, algunos compiladores lo aceptan hoy como una extensión (consulte el comportamiento definido por la implementación de las extensiones en el estándar).

Oye, tengo la siguiente estructura:

typedef struct my_struct{ unsigned long a; unsigned long b; char* c; unsigned int d1 :1; unsigned int d2 :4; unsigned int d3 :4; unsigned int d4 :23; } my_type, *p_type;

El campo d3 está definido actualmente por #define s que van desde 0x00 hasta 0x0D .

En realidad, d3 es una enumeración. Así que es tentador seguir adelante y reemplazar.

unsigned int d3 :4;

por

my_enum d3 :4;

¿Es seguro / permitido?

El código tiene que compilarse con varios.

  • compiladores (GCC, Visual Studio, cosas incrustadas)
  • plataformas (Win32, Linux, cosas incrustadas)
  • Configuraciones (compilar como C, compilar como C ++)

Obviamente, podría dejar la definición de d3 tal como está y usar la enumeración en mi código, asignarla a d3 y así sucesivamente, pero eso no va a funcionar con C ++.


Está permitido en todos los compiladores de C ++, que soporta estándar.

C ++ 03 estándar 9.6 / 3

Un campo de bits tendrá tipo integral o de enumeración (3.9.1). Está definido por la implementación si un campo de bits simple, ni explícitamente firmado ni sin firmar, corto, int o largo está firmado o sin firmar.

C ++ 03 estándar 9.6 / 4

Si el valor de un enumerador se almacena en un campo de bits del mismo tipo de enumeración y el número de bits en el campo de bits es lo suficientemente grande como para contener todos los valores de ese tipo de enumeración, el valor del enumerador original y el valor del campo de bits se comparará igual.

ejemplo

enum BOOL { f=0, t=1 }; struct A { BOOL b:1; }; void f() { A a; a.b = t; a.b == t // shall yield true }

Pero no se puede considerar que la enumeración tiene un tipo subyacente sin firmar.

C ++ 03 estándar 7.2 / 5

El tipo subyacente de una enumeración es un tipo integral que puede representar todos los valores del enumerador definidos en la enumeración. Está definido por la implementación qué tipo de integral se usa como tipo subyacente para una enumeración, excepto que el tipo subyacente no debe ser mayor que int, a menos que el valor de un enumerador no se ajuste a un int o unsigned int


La respuesta será diferente para C y C ++, esta es una para C.

En C los campos de bits están restringidos a signed int , unsigned int , _Bool e int que en este contexto pueden ser cualquiera de los dos primeros. Los implementadores de compiladores pueden agregar a esa lista a su gusto, pero deben documentar los tipos que admiten.

Entonces, para responder a su pregunta, si desea estar absolutamente seguro de que su código es portátil para todos los compiladores de C, no, usar una clase de enum no es una opción.

El párrafo correspondiente de la norma actual dice:

Un campo de bits debe tener un tipo que sea una versión calificada o no calificada de _Bool, int firmado, int firmada o algún otro tipo definido por la implementación. Se define por implementación si se permiten los tipos atómicos.


No.

Los campos de bits se implementan de manera significativamente diferente entre los compiladores. Si define un campo de bits con dos valores, cero y uno, y trata de tener un campo de bits con enumeración, puede tener estos problemas:

El campo de bits no se firmará con gcc y clang, pero se firmará con VC ++. Esto significa que para almacenar cero y uno necesita un campo de bit de dos bits (un campo de bit con signo de un bit solo puede almacenar cero y uno negativo).

Entonces tienes que preocuparte por empacar. VC ++ solo empaquetará campos de bits adyacentes en el mismo almacén de respaldo si sus tamaños coinciden. No estoy seguro de cuáles son las reglas para gcc y clang, pero para VC ++, el almacén de respaldo predeterminado para un campo de bit es un int. Por lo tanto, una serie de campos de bits que son, por ejemplo, una mezcla de bool y enum encajará extremadamente mal con VC ++.

Podría intentar resolver esto con enumeraciones de tipo C ++ 11:

enumeración Foo: unsigned char {one, two};

pero luego gcc se queja si usa esto en un campo de bit de un bit:

advertencia: ''bitfieldTest :: g'' es demasiado pequeño para contener todos los valores de ''enum Foo'' [habilitado de forma predeterminada]

Parece que no hay ganador.