Espacios de nombres
Variantes
Acciones

Declaraciones

De cppreference.com
< c‎ | language

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,
  • Tipos de especificadores:
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.
1-2) Declaración simple. Introduce uno o más identificadores que denotan objetos, funciones, etiquetas estructura/unión/enum, typedefs, o enumeraciones constantes.
3) Declaración de atributos. No declara ningún identificador, y tiene un significado de implentación-definida si el significado no está especificado por el estándar.

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 [ calificadores(opcional) * ]

(4)
declarador-sinpuntero ( parametros-o-identificadores ) (5)
1) El identificador que introduce el declarador.
2) Cualquier declarador puede estar adjunto entre paréntesis; esto se requiere para introducir punteros a arreglos y punteros a funciones.
3) declarador de puntero: la declaración S * cvr D; declara D como un cvr-puntero cualificado al tipo determinado por S.
4) Declador de arreglo: la declaración S D[N] declara D como un arreglo de N objetos del tipo determinado por S. Declarador-sinpuntero es cualquier otro declarador excepto declarador de puntero sin parentesco.
5) Declarador de función: la declaración S D(params) declarada 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