2010-03-11 13 views
25

¿Cuáles son las reglas? OTOH, el caso simple parece implicar que el nuevo tipo es lo último en una línea. Como aquí Uchar es el tipo nuevo:Por favor, explique las reglas de sintaxis y el alcance de "typedef"

typedef unsigned char Uchar; 

Pero un puntero de función es completamente diferente. Aquí el nuevo tipo es pFunc:

typedef int (*pFunc)(int); 

no puede pensar en otros ejemplos mano torpe, pero me he encontrado con algunos usos muy confusos.

Entonces, ¿hay reglas o se supone que las personas deben saber por experiencia que así es como se hace porque lo han visto de esta manera antes?

TAMBIÉN: ¿Cuál es el alcance de un typedef?

+0

también puede investigar 'typedef typename' construir – Anycorn

+2

"Así que hay reglas" - nah, solo inventamos la sintaxis a medida que avanzamos. Los compiladores luego leen nuestras mentes para ver a qué nos referimos. –

+0

@aaa: constructo 'typedef typename'? 'typename' se usa en plantillas para desambiguar tipos. Sería parte de un tipo; no es una forma especial de 'typedef'. –

Respuesta

50

Básicamente un typedef tiene exactamente la misma sintaxis que una declaración de objeto, excepto que tiene el prefijo typedef y que cambia el significado de modo que el nuevo identificador declara un alias para el tipo que el objeto que se hubiera declarado si hubiera sido una declaración normal habría tenido.

A typedef tiene el mismo alcance que la declaración del objeto, por lo que puede ser de ámbito de archivo o local a un bloque o (en C++) a un espacio de nombres o clase.

p. Ej.

declara un int:

int a; 

declara un tipo que es un alias para int:

typedef int a_type; 

declara un puntero a una char:

char *p; 

Declara un alias para a char *:

typedef char *pChar; 

declara una función de puntero:

int (*pFn)(int); 

Declara un alias para el tipo que es 'puntero a una función de tomar int y volviendo int':

typedef int (*pFunc)(int); 
+1

También funciona para cualquier tipo de declaración simple (no solo para declaraciones de objetos). También para declaraciones de funciones: 'typedef void foo();' –

+4

Brilliant; muestra la consistencia de la sintaxis donde el OP no pudo verla. – Clifford

+4

+1, la mejor explicación que he visto en mi vida. –

3

Para mayor comodidad sintáctica, typedef se trata como un especificador de clase de almacenamiento, como extern, static o register. Semánticamente, por supuesto, es bastante diferente, pero cuando se agregó typedef al idioma, era más simple usar una parte de la gramática existente para definir su sintaxis.

Adición static a una declaración de objeto no cambia el significado de la declaración excepto que cambia de clase de almacenamiento del objeto a "estática" (si no lo estaba ya):

{ 
    int foo; /* automatic storage duration */ 
    static int bar; /* static storage duration */ 
} 

Sustitución static con typedef cambia el significado de la declaración, por lo que el nombre que se define no es un nombre de objeto, sino un nombre de tipo (en realidad sólo un alias para un tipo existente):

typedef int baz; /* "baz" is an alias for "int" */ 

La misma sintaxis se aplica a las declaraciones más complejas:

int (*a)[42];   /* a is a pointer to an array of 42 ints */ 
static int (*b)[42]; /* Same as a, but with static storage duration */ 
typedef int (*c)[42] /* c is an alias for the type int(*)[42], or 
         "pointer to array of 42 ints" */ 

Una vez que se dan cuenta que typedef fue empujado de manera arbitraria en la misma ranura en la gramática ocupado por extern, static y register, la comprensión de typedef declaraciones no es más difícil (y sin ¡más fácil!) que entender declaraciones de objetos. (El programa de cdecl y web site son útiles para el desembalaje declaraciones complejas.)

Usted también puede tener un typedef para un tipo de función:

void func(void);    /* declare func as a function */ 
typedef void func_type(void); /* declare func_type as a name 
           for a function type */ 

no se puede utilizar un tipo de función typedef ed para declarar o definir una función, pero se puede utilizar para declarar una función de puntero:

func_type *ptr = func; 

en cuanto a alcance (es decir, la región del programa de t extensión sobre la cual un identificador declarado es visible), un identificador definido por una declaración typedef tiene el mismo alcance que cualquier otro identificador declarado. Si se declara en el alcance del archivo, fuera de cualquier función, es visible desde el punto de declaración hasta el final del archivo. Si se declara dentro de una función, es visible desde el punto en el que se declara hasta el final del bloque circundante más cercano. Y como cualquier declaración, puede ser ocultada por otra declaración con el mismo nombre en un ámbito interno.

+0

Esta respuesta debería tener más votos positivos, ya que explica el problema del alcance (vino aquí solo para eso) – J3STER

+0

@ J3STER: Gracias, pero la respuesta aceptada también aborda el alcance. –

+0

Oh, tienes razón, lo extrañé por completo, (Dislexia menor) – J3STER

Cuestiones relacionadas