c++ - enum - typedef ppt
¿El typedef-name es opcional en una declaración typedef? (3)
Es una sintaxis degenerada que está permitida pero no proporciona ningún beneficio. La mayoría de los compiladores modernos pueden ser provocados para que emitan una advertencia al respecto; por defecto, no pueden. Sin el nombre typedef, la palabra clave typedef
es superflua; en su ejemplo, es completamente equivalente a:
enum test { one };
Otro lugar donde puede ocurrir es con una estructura:
typedef struct SomeThing { int whatever; };
Esto es equivalente a:
struct SomeThing { int whatever; };
Tenga en cuenta que typedef
es oficialmente (o sintácticamente) un ''especificador de clase de almacenamiento'', como static
, extern
, auto
y register
.
C estándar
En ISO / IEC 9899: 1999 (ese es el estándar C), encontramos:
§6.7 Declaraciones
Sintaxis
declaración :
declaradores de especificación init-declarator-list opt ;
declaradores de especificación :
especificación de especificación de clase de almacenamiento especificadores de especificación
especificación de tipo especificación de especificación de especificación
Los especificadores de declaración de calificadores de tipo optan
especificación de la función especificación de los especificadores opt
init-declarator-list :
declarador de inicio
init-declarator-list , init-declarator
init-declarator :
declarador
declarador = inicializador
Y (según lo solicitado):
§6.7.1 Especificadores de clase de almacenamiento
Sintaxis
especificador de clase de almacenamiento:
typedef
extern
static
auto
register
Si realiza un seguimiento a través de esa sintaxis, hay muchas posibilidades degeneradas, y lo que mostró es solo una de las muchas.
Estándar C ++
Es posible que C ++ tenga reglas diferentes.
En ISO / IEC 14882: 1998 (el estándar original de C ++), encontramos en §7.1.1 ''Especificadores de la clase de almacenamiento'' que C ++ no trata a typedef
como una clase de almacenamiento; la lista agrega mutable
y excluye typedef
. Por lo tanto, la especificación gramatical de typedef
en C ++ es definitivamente diferente de la especificación en C.
§7 Declaraciones
Las declaraciones especifican cómo deben interpretarse los nombres. Las declaraciones tienen la forma.
declaración-seq:
declaración
declaración declaración-seq
declaración:
declaración de bloque
definición de la función
declaración de plantilla
instanciación explícita
especialización explícita
vinculación-especificación
definición del espacio de nombres
declaración de bloque:
declaración simple
asm-definition
definición de alias de espacio de nombres
declaración de uso
directiva de uso
declaración simple:
decl-specifier-seq opt init-declarator-list opt ;
...
¶5 Si el decl-specifier-seq contiene el especificador
typedef
, la declaración se denomina declaracióntypedef
y se declara que el nombre de cada declarador deinit-declarator
es un nombre typedef, sinónimo de su tipo asociado (7.1.3).§7.1 Especificadores [dcl.spec]
Los especificadores que se pueden utilizar en una declaración son
decl-especificador:
especificador de clase de almacenamiento
especificador de tipo
especificador de funciones
friend
typedef
decl-specifier-seq:
decl-specifier-seq opt
decl-especificador
§7.1.1 Especificadores de clase de almacenamiento [dcl.stc]
especificador de clase de almacenamiento:
auto
register
static
extern
mutable
§7.1.2 Especificadores de funciones [dcl.fct.spec]
especificador de función:
inline
virtual
explicit
§7.1.3 El especificador typedef [dcl.typedef]
Las declaraciones que contienen el especificador decl-
typedef
declaran identificadores que pueden usarse posteriormente para nombrar tipos fundamentales (3.9.1) o compuestos (3.9.2). El especificadortypedef
no se utilizará en una definición de función (8.4), y no se combinará en un especificador de decl seq con ningún otro tipo de especificador excepto un especificador de tipo.typedef-name:
identificador
...
En un ámbito determinado, se puede utilizar un especificador typedef para redefinir el nombre de cualquier tipo declarado en ese ámbito para hacer referencia al tipo al que ya hace referencia. [Ejemplo:
typedef struct s { /* ... */ } s; typedef int I; typedef int I; typedef I I;
—En ejemplo]
§7.1.4 El amigo especificador [dcl.friend]
El especificador amigo se utiliza para especificar el acceso a los miembros de la clase; ver 11.4.
§7.1.5 Especificadores de tipo [dcl.type]
tipo-especificador:
especificador de tipo simple
especificador de clase
enum-specifier
especificador de tipo elaborado
calificador cv
Dado que §7, ¶5 dice que los nombres typedef
provienen del init-declarator y el init-declarator-list está etiquetado como '' opt '', creo que eso significa que el nombre typedef
puede omitirse en C ++, al igual que en C.
Me sorprendió bastante cuando vi el siguiente código compilado sin errores ni advertencias en g ++ - 4.2:
typedef enum test { one };
Mi suposición era que si utilizaba la palabra clave typedef
, se requeriría un identificador adicional como en:
typedef enum test { one } test;
Como ya se mencionó, g ++ - 4.2 lo acepta sin siquiera una advertencia. Clang ++ 3.0 advierte " warning: typedef requiere un nombre ", Comeau también advierte " warning: statement requiere un nombre typedef ", y g ++ - 4.6 informa: " warning: ''typedef'' se ignoró en esta declaración ".
No he podido identificar en qué parte del estándar está permitido, y me parece un poco confuso que dos de los compiladores adviertan que es necesario , ¿no debería ser un error si se requiere typedef-name pero no está presente?
ACTUALIZACIÓN : he registrado C con los mismos compiladores. Clang y comeau producen la misma salida, gcc da una advertencia: " advertencia: especificador de clase de almacenamiento inútil en declaración vacía ", lo que parece aún más confuso.
ACTUALIZACIÓN : He comprobado la eliminación del nombre de la enumeración y los resultados son los mismos:
typedef enum { one };
De manera similar con una estructura nombrada:
typedef struct named { int x };
Pero no con una estructura sin nombre, en cuyo caso el código fue rechazado en g ++ (4.2 / 4.6) con " error: falta el nombre de tipo en typedef-declaraciones ", gcc (4.2 / 4.6) dio una advertencia: " advertencia: estructura sin nombre / unión que no define instancias ", clang ++" advertencia: la declaración no declara nada ", comeau" error: la declaración requiere un tipo de nombredef "
Lo único que pude encontrar fue lo siguiente en el estándar C ++ 03 §7.1.3 [dcl.typedef] p1
:
typedef-name:
- identificador
Un nombre declarado con el especificador
typedef
se convierte en un typedef-name .
Observe el opt después del identificador faltante, que indica, al menos para mí, que se necesita un identificador para el typedef-name . Es extraño que todos los compiladores probados (silenciosamente) lo acepten.
Editar : Después de la respuesta de @Jonathan, encontré lo siguiente en el mismo estándar que el anterior:
decl-especificador :
- especificador de clase de almacenamiento
- especificador de tipo
- especificador de funciones
friend
typedef
Como puede verse, proporciona un caso adicional para typedef
y la lista de especificadores de clase de almacenamiento confirma esto:
especificador de clase de almacenamiento:
auto
register
static
extern
mutable
Entonces, estamos tan despistados como antes en el caso de C ++.
Realmente se ve como una diferencia C vs. C ++, para mí. C ++ tipifica implícitamente estructuras y uniones a sus etiquetas; así que agregar el typedef es superfluo, pero no es un error. No sé si esto también funciona para las enumeraciones.
Lo que hay que hacer a continuación es ver qué definiciones de variables están permitidas después de estas declaraciones.
enum test etest;
test etest2;
struct named snamed;
named snamed2;