2010-12-08 12 views
5

En mi clase de sistemas operativos recientes tenemos un montón de objetos definidos como tales:struct x vs x_t en C

typedef struct someobj { 
    ... stuff ... 
} someobj_t; 

sé lo que hace muy bien.

La cuestión es que a veces en el código de soporte dado las estructuras se referían a struct someobj *some, y a veces como someobj_t *some. ¿Existe una razón real/útil para referirse a las estructuras de estas dos maneras diferentes, o es solo una diferencia de estilo?

+4

¿Echas de menos un 'typedef'? –

+3

¿Estás seguro de que tienes la pregunta, verdad? 'someobj_t' es un objeto, no un tipo, es posible que haya omitido un solo' typedef' en su código. – Kos

+1

la notación '_t', suponiendo que se refiera a un typedef, si solo fuera una convención para distinguir' struct someobj' y 'someobj' (asumiendo que este era el nombre del tipo definido) - esto es porque C tiene dos" espacios de nombres "diferentes para estos (struct y typedef), y presumiblemente esta convención ayuda a agregar semántica al código. –

Respuesta

5

Suponiendo que estamos preguntando por el código siguiente (no hay typedef en la pregunta ya que estoy escribiendo, pero estoy suponiendo que estaba destinado a estar allí):

typedef struct someobj { 
    // content 
} someobj_t; 

realidad por lo general Sería suficiente omitir el nombre someobj y usar someobj_t consistentemente. Sin embargo hay que situación en la que desea que la estructura para referirse a sí mismo:

typedef struct someobj { 
    struct someobj* next; 
    // cannot say someobj_t* yet - typedef not complete 
} someobj_t; 

// and from now on, both struct someobj and`someobj_t are equivalent 
1

Creo que te refieres

typedef struct someobj { 
... stuff ... 
} someobj_t; 

Esto le permite utilizar someobj_ t como un tipo en lugar de struct someobj. Ambas anotaciones son equivalentes.

2

Los autores puede no saber que se puede (o no prefieren a) omitir el someobj. Si desea sólo una manera de referirse al tipo, entonces se puede escribir:

typedef struct { 
    ... 
} someobj_t; 

Como Kos menciona en otra respuesta, esto está muy bien, siempre y cuando la estructura no tiene por qué referirse a sí misma (por ejemplo, en una lista enlazada). Para conseguir la máxima confusión, siempre se puede hacer:

typedef struct someobj_t { 
    ... 
} someobj_t; 
2

Suponiendo que quería decir:

typedef struct someobj 
{ 
    /* ... */ 
} someobj_t; 

la diferencia en general es simplemente estilística; algunas personas prefieren seguir el nombre de estilo "viejo C" para las estructuras (donde tienes que poner la palabra clave struct en cualquier momento que te refieras a ese tipo), otras como la forma más sintética de simplemente usar someobj_t.

Mucha gente que utiliza el símbolo definido por typedef lo siente más natural porque a menudo provienen de otros idiomas (por ejemplo, C++, C#, ...) donde no hay necesidad de la cosa struct. En muchos casos incluso omiten el nombre struct de la declaración y simplemente dejan el nombre typedef.

El uso de esos dos símbolos es en general equivalente, pero hay algunas advertencias; en primer lugar, antes de que finalice el typedef, la versión _t no existe, por lo que no puede declarar punteros a la estructura dentro de sí utilizando el nombre _t.

Luego, el typedef "existe" solo durante la compilación; esto significa que el compilador y el depurador se referirán a su símbolo con el nombre no typedef.Si utiliza un typedef sin un nombre de estructura "real", cuando tiene que investigar errores con algunos compiladores/depuradores puede volverse loco porque no puede referirse a un nombre de estructura "real", ya que typedef estructuras ed sin un nombre real en realidad son estructuras anónimas.

Esto puede ser especialmente problemático si tiene que exportar su estructura con MIDL y cosas por el estilo; ver this post por Raymond Chen para más detalles.

Por último, pero no menos importante, puede hacer declaraciones directas solo con el nombre de la estructura real; y si no tiene un nombre de estructura (pero solo el typedef) no puede hacer declaraciones directas.

+0

¿Eh? ¿Desde cuándo conoce el vinculador los nombres de los tipos? –

+0

@R .: tienes razón, creo que escribí eso porque estoy acostumbrado a los errores del enlazador en C++, donde el enlazador se refiere al * tipo * de la clase a la que pertenece el método defectuoso (incluso si esos tipos son solo el resultado de exigir los nombres del método). –

6

Mientras que es de usted si se utiliza un typedef struct o el nombre, hay una muy buena razón para no utilizar typedef nombres que terminan en _t. Todos esos nombres están reservados por POSIX para ser utilizados por la implementación, y pueden referirse a tipos específicos de implementación o pueden estandarizarse en versiones futuras de POSIX. Desafortunadamente, muchos autores de la biblioteca ignoran esto.

Personalmente prefiero no usar typedef para las estructuras, pero si elige usarlo, al menos evite el espacio de nombres reservado.

+0

http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html (solo proporciona un enlace a la fuente canónica) –