videos ver significa que programado privado ocultos oculto listado entre diferencia compartir como c++ c enums language-lawyer

c++ - ver - video privado youtube que significa



¿Está permitido que una enumeración tenga un valor no listado? (6)

Situación C ++

En C ++, cada enumeración tiene un tipo integral subyacente. Puede ser corregido, si está explícitamente especificado (por ejemplo, enum test2 : long { a,b}; ) o int por defecto en el caso de una enum con ámbito (por ejemplo: enum class test { a,b }; ):

7.2 / 5: cada enumeración define un tipo que es diferente de todos los demás tipos. Cada enumeración también tiene un tipo subyacente. (...) si no se especifica explícitamente, el tipo subyacente de un tipo de enumeración con ámbito es int. En estos casos, se dice que el tipo subyacente es fijo.

En el caso de una enumeración no codificada donde el tipo subyacente no fue explícitamente corregido ( su ejemplo ), el estándar le da más flexibilidad a su compilador:

7.2 / 6: Para una enumeración cuyo tipo subyacente no es fijo, el tipo subyacente es un tipo integral que puede representar todos los valores del enumerador definidos en la enumeración. (...) Está definido por implementación qué tipo integral se utiliza como el tipo subyacente excepto que el tipo subyacente no debe ser mayor que int a menos que el valor de un enumerador no pueda caber en una int o unsigned int.

Ahora algo muy complicado : los valores que puede contener una variable enum dependen de si el tipo subyacente es fijo o no:

  • si se soluciona, "los valores de la enumeración son los valores del tipo subyacente".

  • otherwhise, son los valores integrales dentro del mínimo y el máximo del bit-field más pequeño que pueden contener el enumerador más pequeño y el más grande.

Estás en el segundo caso, aunque tu código funcionará en la mayoría de los compiladores, el bitfield más pequeño tiene un tamaño de 1 y por lo tanto los únicos valores que puedes mantener con seguridad en todos los compiladores C ++ compatibles son aquellos entre 0 y 1 ... Si desea asegurarse de que puede establecer el valor de 2, o bien debe convertirlo en una enumeración de ámbito, o indicar explícitamente un tipo subyacente.

Más lectura:

Situación C

La situación C es mucho más simple:

6.2.5 / 16: una enumeración comprende un conjunto de valores constantes enteros nombrados. Cada enumeración distinta constituye un tipo enumerado diferente.

Entonces, básicamente, es un int:

6.7.2.2./2 La expresión que define el valor de una constante de enumeración debe ser una expresión constante constante que tiene un valor representable como int.

Con la siguiente restricción:

Cada tipo enumerado debe ser compatible con caracteres, un tipo entero con signo o un tipo entero sin signo. La elección del tipo está definida por la implementación, 128) pero debe ser capaz de representar los valores de todos los miembros de la enumeración.

Esta pregunta ya tiene una respuesta aquí:

Decir, tenemos

enum E { Foo = 0, Bar = 1 };

Ahora, lo hacemos

enum E v = ( enum E ) 2;

Y entonces

switch ( v ) { case Foo: doFoo(); break; case Bar: doBar(); break; default: // Is the compiler required to honor this? doOther(); break; }

Como el interruptor anterior maneja todos los posibles valores listados de la enumeración, ¿está permitido que el compilador optimice la rama default anterior, o tenga un comportamiento no especificado o indefinido en el caso de que el valor de enum no esté en la lista?

Como estoy esperando que el comportamiento sea similar para C y C ++, la pregunta es sobre ambos idiomas. Sin embargo, si hay una diferencia entre C y C ++ para ese caso, sería bueno saberlo también.


Además, 7.2 / 10:

Una expresión de tipo aritmético o de enumeración se puede convertir a un tipo de enumeración explícitamente. El valor no cambia si está en el rango de valores de enumeración del tipo de enumeración; de lo contrario, el valor de enumeración resultante no está especificado.


C ++ Std 7.2.7 [dcl.enum]:

Es posible definir una enumeración que tenga valores no definidos por ninguno de sus enumeradores.

Por lo tanto, puede tener valores de enumeración que no figuran en la lista de enumeradores.

Pero en su caso específico, el ''tipo subyacente'' no es ''fijo'' (7.2.5). La especificación no especifica cuál es el tipo subyacente en ese caso, pero debe ser integral. Como char es el tipo más pequeño, podemos concluir que hay otros valores de la enumeración que no están especificados en la lista de enumeradores.

Por cierto, creo que el compilador puede optimizar su caso cuando puede determinar que no hay otros valores asignados a v, lo cual es seguro, pero creo que no hay compiladores que sean tan inteligentes todavía.


En C enum tipo es un tipo entero lo suficientemente grande como para contener todas las constantes enum :

(C11, 6.7.2.2p4) "Cada tipo enumerado debe ser compatible con char, un tipo entero con signo o un tipo entero sin signo. La elección del tipo está definida por la implementación, 110) pero debe ser capaz de representar los valores de todos los miembros de la enumeración ".

Digamos que el tipo seleccionado para enum E es _Bool . Un objeto _Bool solo puede almacenar los valores 0 y 1 . No es posible tener un objeto _Bool que almacene un valor diferente de 0 o 1 sin invocar un comportamiento indefinido.

En ese caso, el compilador puede suponer que un objeto del tipo de enum E solo puede contener 0 o 1 en un programa estrictamente conformismo y puede optimizar el caso de conmutación default .


En C los enumeradores tienen tipo int . Por lo tanto, cualquier valor entero se puede asignar a un objeto del tipo de enumeración.

Del estándar C (6.7.2.2 especificadores de enumeración)

3 Los identificadores en una lista de enumeradores se declaran como constantes que tienen tipo int y pueden aparecer donde sea que estén permitidos.

En C ++, los enumeradores tienen el tipo de enumeración que lo define. En C ++, debe especificar explícitamente el tipo subyacente o el compilador se calcula el valor máximo permitido.

Del Estándar C ++ (7.2 declaraciones de enumeración)

5 Cada enumeración define un tipo que es diferente de todos los demás tipos. Cada enumeración también tiene un tipo subyacente. El tipo subyacente se puede especificar explícitamente usando enum-base; si no se especifica explícitamente, el tipo subyacente de un tipo de enumeración con ámbito es int. En estos casos, se dice que el tipo subyacente es fijo. Después del paréntesis de cierre de un enumerador de especificación, cada enumerador tiene el tipo de su enumeración .

Por lo tanto, en C, cualquier valor posible de una enumeración es cualquier valor entero. El compilador puede no optimizar un interruptor que elimina la etiqueta predeterminada.


En C y C ++, esto puede funcionar.

Mismo código para ambos:

#include <stdio.h> enum E { Foo = 0, Bar = 1 }; int main() { enum E v = (enum E)2; // the cast is required for C++, but not for C printf("v = %d/n", v); switch (v) { case Foo: printf("got foo/n"); break; case Bar: printf("got bar/n"); break; default: printf("got /n", v); break; } }

Mismo resultado para ambos:

v = 2 got default

En C, una enum es un tipo integral, por lo que puede asignarle un valor entero sin fundir. En C ++, una enum es de su propio tipo.