Declaraciones
Una declaración es un constructor del lenguaje C que introduce uno o más identificadores en el programa y especifica su significado y propiedades.
Las declaraciones pueden aparecer cualquier ámbito. Cada declaración termina con un punto y coma (al igual que una sentencia) y consiste de dos tres distintas partes:
especificadores-y-calificadores declaradores-e-inicializadores(opcional) ;
|
(1) | ||||||||
atrib-espe-sec especificadores-y- calificadores declaradores-e-inicializadores ;
|
(2) | (desde C23) | |||||||
atrib-espe-sec ;
|
(3) | (desde C23) | |||||||
donde
especificadores-y-calificadores | - | de lista separada-por-espacios-en-blanco, en cualquier orden,
|
declaradores-e-inicializadores | - | lista de declaradores separados-por-coma declaradores (cada declarador proporciona información de tipo adicional y/o el identificador a declarar). Los declaradores pueden ser acompañados por inicializadores. Los declaradores enum, estructura, y unión pueden omitir declaradores, en cuyo caso sólo introducen las constantes de enumeración y/o las etiquetas. |
atrib-espe-sec | - | (C23)lista opcional de atributos, aplicado a declarar entidades, o forma de declaración de atributo si aparecen solas. |
Por ejemplo,
int a, *b=NULL; // "int" es el tipo de especificador, // "a" es un declarador // "*b" es un declarador y NULL es su inicializador const int *f(void); // "int" es el tipo de especificador // "const" es el tipo de calificador // "*f(void)" es el declarador enum COLOR {RED, GREEN, BLUE} c; // "enum COLOR {RED, GREEN, BLUE}" es el tipo de especificador // "c" es el declarador
El tipo de cada identificador introducido en una declaración está determinado por una combinación del tipo especificado por el especificador de tipo y el tipo de modificaciones aplicado por su declarador.
Atributos(desde C23) pueden aparecer en especificadores-y-calificadores, en cuyo caso se aplican al tipo determinado por los especificadores precedentes.
[editar] Declaradores
Cada declarador es alguno de los siguientes:
identificador atrib-espe-sec(opcional) | (1) | ||||||||
( declarador )
|
(2) | ||||||||
* atrib-espe-sec(opcional) calificadores(opcional) declarador
|
(3) | ||||||||
declarador-sinpuntero [ static (opcional) calificadores(opcional) expresion ]
declarador-sinpuntero |
(4) | ||||||||
declarador-sinpuntero ( parametros-o-identificadores )
|
(5) | ||||||||
D
como un cvr-puntero cualificado al tipo determinado por S
.D
como un arreglo de N
objetos del tipo determinado por S
. Declarador-sinpuntero es cualquier otro declarador excepto declarador de puntero sin parentesco.D
como una función tomando los parámetros params
y retornando S
. declador-sinpuntero es cualquier otro declarador excepto declarador de puntero sin parentesco.El razonamiento detrás de esta sintaxis es que cuando el identificador declarado por el declarador aparece en una expresión de la misma forma que el declarador, tendría el tipo especificado por la secuencia del especificador de tipo. |- | colspan="10" class="t-sdsc-sep" |
|}
struct C { int member; // "int" es el especificador de tipo. // "member" es el declarador } obj, *pObj = &obj; // "struct C { int member; }" es el especificador de tipo // El declarador "obj" define un objeto de tipo struct C // El declarador "*pObj" declara un puntero a C, // El inicializador "= &obj" proporciona el valor inicial para ese puntero. int a = 1, *p = NULL, f(void), (*pf)(double); // El especificador de tipo es "int" // El declarador "a" define un objeto de tipo int // El inicializador "=1" proporciona su valor inicial // El declarador "*p" define un objeto de tipo puntero a int // El inicializador "=NULL" proporciona su valor inicial // El declarador "f(void)" declara una función tomando void y retornando int // El declarador "(*pf)(double)" define un objeto de tipo puntero // a función tomando double y retornando int int (*(*foo)(double))[3] = NULL; // el especificador de tipo es int // 1. El declarador "(*(*foo)(double))[3]" es un declarador de ''array'': // El tipo declarado es "/declarador anidado/ de ''array'' de 3 int" // 2. El declarador anidado es "*(*foo)(double))", el cual es un declarador de puntero // El tipo declarado es "/declarador anidado/ de puntero a ''array'' de 3 int" // 3. El declarador anidado es "(*foo)(double)", el cual es un declarador de función // El tipo declarado es "/declarador anidado/ de función tomando double y retornando // un puntero a ''array'' de 3 int" // 4. El declarador anidado es "(*foo)" que es un (entre paréntesis, como es requerido por // la sintaxis del declarador de función) declarador de puntero. // El tipo declarado es "/declarador anidado/ de puntero a función tomando double // y retornando puntero a ''array'' de 3 int" // 5. El declarador anidado es "foo", el cual es un identificador. // La declaración introduce el identificador "foo" para referirse a un objeto de tipo // "puntero a función tomando double y retornando puntero a ''array'' de 3 int" // El inicializador "= NULL" proporciona el valor inicial de este puntero. // Si "foo" es usado en una expresión de la forma de el declarador, su tipo sería // int. int x = (*(*foo)(1.2))[0];
El final de cada declarador que no forma parte de otro declarador es un punto de secuencia.
En todos los casos, atrib-espe-sec es una secuencia opcional de atributos(desde C23). Cuando aparece inmediatamente después del identificador, se aplica al objeto o la función que está siendo declarada.
[editar] Definiciones
Una definición es una declaración que proporciona toda la información acerca de los identificadores que declara.
Cada declaración de un enum o un typedef es una definición.
Para funciones, una declaración que incluye el cuerpo de una función es una definición de función:
int foo(double); // declaración int foo(double x){ return x; } // definición
Para objetos, una declaración que asigna almacenamiento (automático o estático, pero no externo) es una definición, mientras que una declaración que no asigna almacenamiento (declaración externa) no lo es.
extern int n; // declaración int n = 10; // definición
Para estructuras y uniones, las declaraciones que especifican la lista de miembros son definiciones:
struct X; // declaración struct X { int n; }; // definición