2011-07-25 31 views
8

Tengo una pregunta rápida sobre C style struct's. Yo estaba cavando a través de un código de ejemplo y encontré una estructura declarada de la siguiente manera:C struct struct declaration

typedef struct _STRUCTNAME 
{ 
    // struct contents 
} STRUCTNAME; 

Tenga en cuenta la falta de un guión en el segundo tiempo STRUCTNAME aparece. Según entendí, esto declararía un único _STRUCTNAME llamado STRUCTNAME y no se podrían crear más objetos de esta estructura.

Sin embargo, este no parece ser el caso. Una estructura de este tipo nunca fue en realidad una instancia en el código, excepto en un solo lugar: en una matriz global de este tipo de objetos que se utilizó en lugares al azar:

const struct STRUCTNAME ARRAYNAME[] = 
{ 
    // various STRUCTNAMEs declared here 
}; 

nota la falta de un guión de nuevo (lo cual me pareció el nombre del objeto instanciado?)

¿Está completamente fuera de mi comprensión?

¿Podría alguien explicar?

Respuesta

4

STRUCTNAME es el nombre typedef.

_STRUCTNAME es la 'etiqueta' para la estructura, que está en un espacio de nombres diferente.

Antes de la estandarización de ANSI, el espacio de nombres de la etiqueta de estructura no estaba separado en muchos compiladores, por lo que para evitar una colisión de nombre con el nombre de typedef tenía que ser diferente. Sin embargo, desde la estandarización no hay necesidad de que el nombre de la etiqueta sea diferente.

Usted ve este idioma a menudo utilizado en el código de Windows, sin duda porque era así en muchos ejemplos del SDK. Raymond Chen escribió una entrada de blog sobre él hace un tiempo:

Además, estoy seguro de que habrá algunos comentarios acerca de cómo el identificador _STRUCTNAME está reservado para la puesta en práctica, así que no es una buena idea para usar esa forma en cualquier caso.

+0

Podría explicar qué quiere decir con "etiqueta"? – Klauss

+2

"etiqueta" es simplemente el término que el estándar C usa para el nombre/identificador dado a una estructura, unión o enumeración. –

7
typedef struct _STRUCTNAME 
{ 
    // struct contents 
} STRUCTNAME; 

Esta pieza de código hace dos cosas:

  1. define una estructura llamada struct _STRUCTNAME y
  2. Crea un typedef de esa estructura llamada STRUCTNAME.

La razón de esto es que en el código apropiado C, la forma en que sería de otro modo declarar una struct (como el anterior) sería el siguiente:

struct _STRUCTNAME structInstance; 

Sin embargo, con el typedef en su lugar, puede simplemente usar la siguiente:

STRUCTNAME structInstance; 

lo mismo es cierto para enum declaraciones.

0

Creo que su confusión es por qué la lista de identificadores al final de la struct definición no está instanciando instancias. La razón es porque ha incluido la palabra clave typedef.

Considere el syantax para typedef:

typedef type-definition identifier; 

Lo que han hecho está previsto que su struct como el tipo de definición. En lugar de crear instancias, está definiendo un tipo. Constrast esto a instancias instanciar donde la estructura es simplemente definir el tipo en línea:

struct STRUCTNAME 
{ 
    // struct contents 
} myStruct, *ptr, alsoMyStruct; 

Cuando no se incluye la palabra clave typedef, el identificador simplemente especifica los casos como de costumbre.

2

Michael Burr dijo:

Además, estoy seguro de que habrá algunos comentarios acerca de cómo el identificador _STRUCTNAME está reservado para la aplicación, por lo que no es una buena idea usar esa forma, en cualquier caso.

bien, estoy juego (pero quería algo de formato para que pueda obtener una respuesta en su lugar):

Un estándar de la lengua es un contrato entre el compilador escritor y recopilador-usuario, donde cada uno se compromete a hacer y no hacer ciertas cosas

La mayoría de los identificadores que comienzan con _ se reservan para la implementación - incluyendo todos los identificadores que comienzan con _ seguido de una letra mayúscula. Esto significa que el compilador-escritor puede usarlos para cualquier propósito, porque el compilador-usuario ha prometido no usarlos.

Los compiladores que rompen su promesa obtienen resultados raros.

Por el contrario, todos los identificadores que el estándar [aplicable] no reserva para la implementación están garantizados para estar disponibles para el usuario del compilador porque el compilador-escritor ha prometido no usarlos.

Los compiladores que incumplen sus promesas obtienen demandas de reembolso, cuando el código válido obtiene resultados extraños.

Mi preferencia es poner un _ final en los nombres de las etiquetas, incluir guardias, etc., asegurando que me quedo fuera del espacio de la implementación; por lo tanto:

typedef struct STRUCTNAME_ 
{ 
    // struct contents 
} STRUCTNAME; 

(. Algunos puristas desaprueban azúcar como meramente sintáctica typedef s, pero C necesita un poco de azúcar aquí y allá, de lo contrario, puede parecer bastante soso)

0
const struct STRUCTNAME ARRAYNAME[] = 
{ 
    // various STRUCTNAMEs declared here 
}; 

el código anterior no va a compilar para el tipo incompleto para la matriz.Creo tros typo que debería ser

const struct _STRUCTNAME ARRAYNAME[] = ... 

Alternativamente, puede utilizar la palabra clave typedef struct sin especificar

const STRUCTNAME ARRAYNAME[] =