2011-10-29 5 views
5

Soy consciente de dos posibles maneras de definir y utilizar struct s:código struct escritura que funciona tanto en C y en C++

#1 
struct person 
{ 
    char name[32]; 
    int age; 
}; 

struct person dmr = {"Dennis Ritchie", 70}; 

#2 
typedef struct 
{ 
    char name[32]; 
    int age; 
} person; 

person dmr = {"Dennis Ritchie", 70}; 

La propiedad interesante de la primera manera es que tanto el tipo como la variable puede tener el mismo nombre:

struct person person = {"Sam Persson", 50}; 

¿Es eso idiomático en C? ¿Está garantizado para trabajar en C++? ¿O hay casos de esquina que debería conocer?

Tenga en cuenta que no estoy interesado en respuestas puras de C++ (por ejemplo, "use std::string en lugar de char[32]"). Esta es una pregunta acerca de la compatibilidad C/C++.

+0

No llamaría a esa "propiedad interesante" más bien una propiedad oscurecedora. Es mejor mantener los nombres de tipos comenzando desde mayúsculas, para distinguir los nombres de tipo y variable. –

+0

He marcado esto como duplicado de [typedef struct vs struct definitions] (http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions). Técnicamente puede considerar que no lo es (la otra pregunta solo trata sobre C) pero la semántica es la misma en C++ con la única diferencia de que la búsqueda también encontrará símbolos en el espacio identificador definido por el usuario si no los encuentra en el espacio de identificador global. Eso también se trata en la respuesta aceptada (que contiene bits de C++) –

+1

Además, son ** no ** dos formas de definir una 'struct', hay una sola forma de definir una' struct' (que puede tener o no es un nombre), y hay 'typedef's (que se pueden aplicar a un tipo nombrado o sin nombre), pero no son dos maneras de definir una 'estructura' en cualquier caso. Y te falta 3), combinando ambos: 'typedef struct type {} type;' para lo que vale (que es la forma idiomática de C) –

Respuesta

1
struct person person = {"Sam Persson", 50}; 

No es idiomático utilizar el mismo identificador para un tipo y una variable. En Unix, es típico usar una versión abreviada para el nombre de la variable, por ejemplo: struct stat st, struct timeval tv, ... de la misma manera fd es un nombre típico para una variable de descriptor de archivo.

3

struct son compatibles entre C & C++ solo cuando son POD -s.

que tienden a codificar algo como:

struct person_st { char name[32]; int age; }; 
typedef struct person_st Person_t; 
+2

Entonces, ¿qué son 'POD' struct' de C? – xanatos

+0

@xantos, 'clase'es! Pero en lugar de 'clase' escribes 'struct' y los miembros son' public' por defecto en oposición a 'private' en' class'es – Shahbaz

+0

@Shahbaz: No hay clases en C. Supongo que eso es lo que significa xanatos. – fredoverflow

0

No estoy seguro de si sería totalmente correcto en C++ estándar, pero probado con g++ -pedantic -Wall y tiene errores ni advertencias (tenga en cuenta que este doesn' t necesariamente significa que es completamente estándar. g ++, incluso con -pedantic, no se toma la molestia de dar una advertencia para todos los códigos no estándar.) (¿Alguien conoce la especificación de C++ lo suficiente como para comentar si es realmente estándar o no? ?)

La cosa con escritura:

struct person person = {...}; 

es que en C++, person ambos se refieren a la variable y al tipo. En C, esto no fue un problema simplemente porque person no es del tipo (struct person es). Aunque desde el contexto, con las pocas pruebas que escribí con g ++, el compilador no tuvo problemas para entender cuándo estoy pidiendo la variable y cuándo para el tipo, creo que podría confundirse en algún momento. Una cosa confusa que he descubierto es que si usted tiene:

struct person *person = ...; 

continuación sizeof(person) devuelve el tamaño de la variable, mientras que para obtener el tamaño del tipo, debe escribir sizeof(struct person) que puedo asegurar, no C++ codificador recordaría escribir el stuct.

Lo mejor es evitar todo tipo de confusión. I suelo hacer esto para el código que podría ser utilizado tanto en C y C++:

typedef struct person 
{ 
    ... 
} person; 

Dar un nombre a la struct que está siendo typedef ed permite al programador utilice cualquiera person o struct person. Por lo tanto, un poco de flexibilidad (sin mencionar que no tiene que cambiar el código ya escrito después de typedef en el struct.

+1

Para el ejemplo 'sizeof'. ver el estándar de C++ §9.1 ¶2 _Si un nombre de clase se declara en un ámbito donde también se declara una variable, función o enumerador del mismo nombre, cuando ambas declaraciones están dentro del alcance, se puede hacer referencia a la clase solo utilizando un elaborated-type-specifier_ – ninjalj

+0

No, en C++ para su primer ejemplo 'person' se referiría a la variable. –

2

Declaro que tengan el mismo nombre en tanto la etiqueta de estructura y espacios de nombres identificador global:

#ifdef __cplusplus 
extern "C" { 
#endif 

typedef struct person 
{ 
    char name[32]; 
    int age; 
} person; 

#ifdef __cplusplus 
} 
#endif 

En uso, que no requiere el uso de la etiqueta de estructura en ambas traducciones C y C++:

person dmr = {"Dennis Ritchie", 70}; 

Si prefiere la etiqueta struct en algunos lugares, también puede usarla de esa manera.

El beneficio obvio es que el tipo puede ser referido por cualquiera de los identificadores en ambos espacios de nombres, independientemente del idioma.