El significado de ambos se me escapa.
El significado de ambos se me escapa.
Respuestas:
Una declaración introduce un identificador y describe su tipo, ya sea un tipo, objeto o función. Una declaración es lo que el compilador necesita para aceptar referencias a ese identificador. Estas son declaraciones:
extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations
Una definición en realidad instancia / implementa este identificador. Es lo que necesita el vinculador para vincular referencias a esas entidades. Estas son definiciones correspondientes a las declaraciones anteriores:
int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};
Se puede usar una definición en lugar de una declaración.
Un identificador se puede declarar con la frecuencia que desee. Por lo tanto, lo siguiente es legal en C y C ++:
double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);
Sin embargo, debe definirse exactamente una vez. Si olvida definir algo que ha sido declarado y referenciado en alguna parte, entonces el vinculador no sabe a qué vincular las referencias y se queja de la falta de símbolos. Si define algo más de una vez, el vinculador no sabe a qué definiciones vincular referencias y se queja de símbolos duplicados.
Dado que el debate sobre qué es una declaración de clase frente a una definición de clase en C ++ sigue apareciendo (en respuestas y comentarios a otras preguntas), pegaré una cita del estándar de C ++ aquí.
En 3.1 / 2, C ++ 03 dice:
Una declaración es una definición a menos que [...] sea una declaración de nombre de clase [...].
3.1 / 3 luego da algunos ejemplos. Entre ellos:
[Ejemplo: [...] struct S {int a; int b; }; // define S, S :: a y S :: b [...] estructura S; // declara S —Ejemplo
Para resumir: el estándar C ++ considera struct x;
que es una declaración y struct x {};
una definición . (En otras palabras, "declaración hacia adelante" es un nombre inapropiado , ya que no hay otras formas de declaraciones de clase en C ++).
Gracias a litb (Johannes Schaub) que desenterró el capítulo y el verso en una de sus respuestas.
extern int i
es una declaración, ya que solo introduce / especifica i
. Puede tener tantos extern int i
en cada unidad de compilación como desee. int i
Sin embargo, es una definición. Denota el espacio para que el entero esté en esta unidad de traducción y aconseja al vinculador que vincule todas las referencias a i
esta entidad. Si tiene más o menos de una de estas definiciones, el vinculador se quejará.
int i;
en archivo / alcance global o alcance de función es una definición tanto en C como en C ++. En C porque asigna almacenamiento, y en C ++ porque no tiene el especificador externo o una especificación de enlace. Esto equivale a lo mismo, que es lo que dice sbi: en ambos casos, esta declaración especifica el objeto al que deben vincularse todas las referencias a "i" en ese ámbito.
struct A { double f(int, double); double f(int, double); };
inválido, por supuesto. Sin embargo, está permitido en otros lugares. Hay algunos lugares donde se puede declarar cosas, pero no definen, también: void f() { void g(); }
válida, pero no el siguiente: void f() { void g() { } };
. ¿Qué es una definición y qué declaración tiene reglas sutiles cuando se trata de plantillas? ¡Cuidado! +1 para una buena respuesta sin embargo.
Desde el estándar C ++ sección 3.1:
Una declaración introduce nombres en una unidad de traducción o redeclara nombres introducidos por declaraciones anteriores. Una declaración especifica la interpretación y los atributos de estos nombres.
El siguiente párrafo establece (énfasis mío) que una declaración es una definición a menos que ...
... declara una función sin especificar el cuerpo de la función:
void sqrt(double); // declares sqrt
... declara un miembro estático dentro de una definición de clase:
struct X
{
int a; // defines a
static int b; // declares b
};
... declara un nombre de clase:
class Y;
... contiene la extern
palabra clave sin un inicializador o cuerpo de función:
extern const int i = 0; // defines i
extern int j; // declares j
extern "C"
{
void foo(); // declares foo
}
... o es una typedef
o using
declaración.
typedef long LONG_32; // declares LONG_32
using namespace std; // declares std
Ahora, por la gran razón por la cual es importante entender la diferencia entre una declaración y una definición: la regla de una definición . De la sección 3.2.1 del estándar C ++:
Ninguna unidad de traducción contendrá más de una definición de variable, función, tipo de clase, tipo de enumeración o plantilla.
struct x {static int b = 3; };
?
b
que también se declare const
. Consulte stackoverflow.com/a/3536513/1858225 y daniweb.com/software-development/cpp/threads/140739/… .
Declaración: "En algún lugar, existe un foo".
Definición: "... y aquí está!"
Hay casos extremos interesantes en C ++ (algunos de ellos también en C). Considerar
T t;
Eso puede ser una definición o una declaración, dependiendo de qué tipo T
es:
typedef void T();
T t; // declaration of function "t"
struct X {
T t; // declaration of function "t".
};
typedef int T;
T t; // definition of object "t".
En C ++, cuando se usan plantillas, hay otro caso límite.
template <typename T>
struct X {
static int member; // declaration
};
template<typename T>
int X<T>::member; // definition
template<>
int X<bool>::member; // declaration!
La última declaración no fue una definición. Es la declaración de una especialización explícita del miembro estático de X<bool>
. Le dice al compilador: "Si se trata de crear instancias X<bool>::member
, no cree una instancia de la definición del miembro de la plantilla principal, sino que use la definición que se encuentra en otro lugar". Para que sea una definición, debe proporcionar un inicializador
template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.
Declaración
Las declaraciones le dicen al compilador que existe un elemento o nombre del programa. Una declaración introduce uno o más nombres en un programa. Las declaraciones pueden ocurrir más de una vez en un programa. Por lo tanto, se pueden declarar clases, estructuras, tipos enumerados y otros tipos definidos por el usuario para cada unidad de compilación.
Definición
Las definiciones especifican qué código o datos describe el nombre. Se debe declarar un nombre antes de poder usarlo.
class foo {};
es una definición de clase , ¿no?
Del estándar C99, 6.7 (5):
Una declaración especifica la interpretación y los atributos de un conjunto de identificadores. Una definición de un identificador es una declaración para ese identificador que:
Del estándar C ++, 3.1 (2):
Una declaración es una definición a menos que declare una función sin especificar el cuerpo de la función, contiene el especificador externo o una especificación de vinculación y ni un inicializador ni un cuerpo de función, declara un miembro de datos estáticos en una declaración de clase, es un declaración de nombre de clase, o es una declaración typedef, una declaración de uso o una directiva de uso.
Entonces hay algunos ejemplos.
De manera interesante (o no, pero me sorprende un poco), typedef int myint;
es una definición en C99, pero solo una declaración en C ++.
typedef
, ¿no significa eso que podría repetirse en C ++, pero no en C99?
De wiki.answers.com:
El término declaración significa (en C) que le está informando al compilador sobre el tipo, tamaño y, en caso de declaración de función, tipo y tamaño de sus parámetros de cualquier variable, o tipo o función definidos por el usuario en su programa. No se reserva espacio en la memoria para ninguna variable en caso de declaración. Sin embargo, el compilador sabe cuánto espacio reservar en caso de que se cree una variable de este tipo.
por ejemplo, las siguientes son todas las declaraciones:
extern int a;
struct _tagExample { int a; int b; };
int myFunc (int a, int b);
La definición, por otro lado, significa que además de todas las cosas que hace la declaración, el espacio también está reservado en la memoria. Puede decir "DEFINICIÓN = DECLARACIÓN + RESERVA DE ESPACIO" a continuación hay ejemplos de definición:
int a;
int b = 0;
int myFunc (int a, int b) { return a + b; }
struct _tagExample example;
ver respuestas .
struct foo {};
es una definición , no una declaración. Una declaración de foo
sería struct foo;
. A partir de eso, el compilador no sabe cuánto espacio reservar para los foo
objetos.
struct foo;
es una declaración, pero no le dice al compilador el tamaño de foo. Añadiría que struct _tagExample { int a; int b; };
es una definición. Entonces, en este contexto, es engañoso llamarlo una declaración. Por supuesto, es una, ya que todas las definiciones son declaraciones, pero parece estar sugiriendo que no es una definición. Es una definición, de _tagExample.
Como no veo una respuesta pertinente a C ++ 11, aquí hay una.
Una declaración es una definición a menos que declare a / n:
enum X : int;
template<typename T> class MyArray;
int add(int x, int y);
using IntVector = std::vector<int>;
static_assert(sizeof(int) == 4, "Yikes!")
;
Cláusulas adicionales heredadas de C ++ 03 por la lista anterior:
int add(int x, int y);
extern int a;
oextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
using namespace NS;
Una declaración de plantilla es una declaración. Una declaración de plantilla también es una definición si su declaración define una función, una clase o un miembro de datos estático.
Ejemplos del estándar que diferencia entre declaración y definición que encontré útil para comprender los matices entre ellos:
// except one all these are definitions
int a; // defines a
extern const int c = 1; // defines c
int f(int x) { return x + a; } // defines f and defines x
struct S { int a; int b; }; // defines S, S::a, and S::b
struct X { // defines X
int x; // defines non-static data member x
static int y; // DECLARES static data member y
X(): x(0) { } // defines a constructor of X
};
int X::y = 1; // defines X::y
enum { up , down }; // defines up and down
namespace N { int d; } // defines N and N::d
namespace N1 = N; // defines N1
X anX; // defines anX
// all these are declarations
extern int a; // declares a
extern const int c; // declares c
int f(int); // declares f
struct S; // declares S
typedef int Int; // declares Int
extern X anotherX; // declares anotherX
using N::d; // declares N::d
// specific to C++11 - these are not from the standard
enum X : int; // declares X with int as the underlying type
using IntVector = std::vector<int>; // declares IntVector as an alias to std::vector<int>
static_assert(X::y == 1, "Oops!"); // declares a static_assert which can render the program ill-formed or have no effect like an empty declaration, depending on the result of expr
template <class T> class C; // declares template class C
; // declares nothing
Definición :
extern int a; // Declaration
int a; // Definition
a = 10 // Initialization
int b = 10; // Definition & Initialization
La definición asocia la variable con un tipo y asigna memoria, mientras que la declaración solo especifica el tipo pero no asigna memoria. La declaración es más útil cuando desea hacer referencia a la variable antes de la definición.
* No confunda definición con inicialización. Ambos son diferentes, la inicialización le da valor a la variable. Ver el ejemplo anterior.
Los siguientes son algunos ejemplos de definición.
int a;
float b;
double c;
Ahora declaración de función:
int fun(int a,int b);
Tenga en cuenta el punto y coma al final de la función, por lo que dice que es solo una declaración. El compilador sabe que en algún lugar del programa esa función se definirá con ese prototipo. Ahora, si el compilador obtiene una función, llame a algo como esto
int b=fun(x,y,z);
El compilador arrojará un error diciendo que no existe tal función. Porque no tiene ningún prototipo para esa función.
Tenga en cuenta la diferencia entre dos programas.
Programa 1
#include <stdio.h>
void print(int a)
{
printf("%d",a);
}
main()
{
print(5);
}
En esto, la función de impresión se declara y define también. Dado que la llamada a la función viene después de la definición. Ahora vea el próximo programa.
Programa 2
#include <stdio.h>
void print(int a); // In this case this is essential
main()
{
print(5);
}
void print(int a)
{
printf("%d",a);
}
Es esencial porque la llamada a la función precede a la definición, por lo que el compilador debe saber si existe tal función. Entonces declaramos la función que informará al compilador.
Definición :
Esta parte de definir una función se llama Definición. Dice qué hacer dentro de la función.
void print(int a)
{
printf("%d",a);
}
int a; //declaration; a=10; //definition
Esto está completamente mal. Cuando se habla de objetos de duración de almacenamiento automático (objetos declarados dentro de una definición de función que no se declara con otro especificador de clase de almacenamiento como extern), estas siempre son definiciones.
definición significa función real escrita y declaración significa función simple para declarar, por ejemplo
void myfunction(); //this is simple declaration
y
void myfunction()
{
some statement;
}
esta es la definición de la función myfunction
Regla de oro:
Una declaración le dice al compilador cómo interpretar los datos de la variable en la memoria. Esto es necesario para cada acceso.
Una definición reserva la memoria para hacer que la variable exista. Esto tiene que suceder exactamente una vez antes del primer acceso.
Para entender los sustantivos, centrémonos primero en los verbos.
declarar : anunciar oficialmente; proclamar
definir - para mostrar o describir (alguien o algo) clara y completamente
Entonces, cuando declaras algo, solo dices qué es .
// declaration
int sum(int, int);
Esta línea declara una función llamada C sum
que toma dos argumentos de tipo int
y devuelve un int
. Sin embargo, aún no puedes usarlo.
Cuando proporcionas cómo funciona realmente , esa es la definición.
// definition
int sum(int x, int y)
{
return x + y;
}
Para comprender la diferencia entre declaración y definición, necesitamos ver el código de ensamblaje:
uint8_t ui8 = 5; | movb $0x5,-0x45(%rbp)
int i = 5; | movl $0x5,-0x3c(%rbp)
uint32_t ui32 = 5; | movl $0x5,-0x38(%rbp)
uint64_t ui64 = 5; | movq $0x5,-0x10(%rbp)
double doub = 5; | movsd 0x328(%rip),%xmm0 # 0x400a20
movsd %xmm0,-0x8(%rbp)
y esta es solo la definición:
ui8 = 5; | movb $0x5,-0x45(%rbp)
i = 5; | movl $0x5,-0x3c(%rbp)
ui32 = 5; | movl $0x5,-0x38(%rbp)
ui64 = 5; | movq $0x5,-0x10(%rbp)
doub = 5; | movsd 0x328(%rip),%xmm0 # 0x400a20
movsd %xmm0,-0x8(%rbp)
Como puedes ver nada cambia.
La declaración es diferente de la definición porque proporciona información utilizada solo por el compilador. Por ejemplo, uint8_t le dice al compilador que use la función asm movb.
Mira eso:
uint def; | no instructions
printf("some stuff..."); | [...] callq 0x400450 <printf@plt>
def=5; | movb $0x5,-0x45(%rbp)
La declaración no tiene una instrucción equivalente porque no es algo que se ejecute.
Además, la declaración le dice al compilador el alcance de la variable.
Podemos decir que la declaración es una información utilizada por el compilador para establecer el uso correcto de la variable y por cuánto tiempo alguna memoria pertenece a cierta variable.
¿No podría decir en los términos más generales posibles, que una declaración es un identificador en el que no se asigna almacenamiento y una definición realmente asigna el almacenamiento de un identificador declarado?
Una idea interesante: una plantilla no puede asignar almacenamiento hasta que la clase o función esté vinculada con la información de tipo. Entonces, ¿el identificador de plantilla es una declaración o definición? Debería ser una declaración ya que no se asigna almacenamiento, y simplemente está 'creando prototipos' de la clase o función de plantilla.
template<class T> struct foo;
es una declaración de plantilla , y también lo es template<class T> void f();
. Las definiciones de plantilla reflejan las definiciones de clase / función de la misma manera. (Tenga en cuenta que el nombre de una plantilla no es un nombre de tipo o función . Un lugar donde puede ver esto es cuando no puede pasar una plantilla como parámetro de tipo de otra plantilla. Si desea pasar plantillas en lugar de tipos, necesita parámetros de plantilla de plantilla. )
Encuentra respuestas similares aquí: Preguntas de la entrevista técnicos en C .
Una declaración proporciona un nombre al programa; Una definición proporciona una descripción única de una entidad (por ejemplo, tipo, instancia y función) dentro del programa. Las declaraciones pueden repetirse en un ámbito dado, introduce un nombre en un ámbito determinado.
Una declaración es una definición a menos que:
Una definición es una declaración a menos que:
Esto va a sonar realmente cursi, pero es la mejor manera en que he podido mantener los términos en mi cabeza:
Declaración: Imagine a Thomas Jefferson dando un discurso ... "¡DECLARO QUE ESTA FOO EXISTE EN ESTE CÓDIGO DE FUENTE!"
Definición: imagina un diccionario, estás buscando Foo y lo que realmente significa.
De acuerdo con el manual de la biblioteca GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )
En C, una declaración simplemente proporciona información de que existe una función o variable y da su tipo. Para una declaración de función, también se puede proporcionar información sobre los tipos de sus argumentos. El propósito de las declaraciones es permitir que el compilador procese correctamente las referencias a las variables y funciones declaradas. Una definición, por otro lado, en realidad asigna almacenamiento para una variable o dice lo que hace una función.
El concepto de Declaración y Definición formará una trampa cuando use la clase de almacenamiento externo porque su definición estará en otra ubicación y declarará la variable en su archivo de código local (página). Una diferencia entre C y C ++ es que en C usted las declaraciones se realizan normalmente al comienzo de una función o página de códigos. En C ++ no es así. Puede declarar en el lugar que elija.
Mi ejemplo favorito es "int Num = 5" aquí su variable es 1. definida como int 2. declarada como Num y 3. instanciada con un valor de cinco. Nosotros
Una clase o estructura le permite cambiar cómo se definirán los objetos cuando se use más tarde. Por ejemplo
Cuando aprendemos a programar estos dos términos a menudo se confunden porque a menudo hacemos ambos al mismo tiempo.
Etapas de una generación ejecutable:
(1) preprocesador -> (2) traductor / compilador -> (3) enlazador
En la etapa 2 (traductor / compilador), las declaraciones de declaración en nuestro código le dicen al compilador que estas cosas las vamos a usar en el futuro y puede encontrar la definición más adelante, el significado es:
traductor asegúrese de que: ¿qué es qué? significa declaración
y (3) la etapa (enlazador) necesita definición para unir las cosas
Linker asegúrese de que: ¿ dónde está qué? significa definición
Hay algunas definiciones muy claras esparcidas por K&R (segunda edición); ayuda ponerlos en un solo lugar y leerlos como uno:
"Definición" se refiere al lugar donde se crea la variable o se le asigna almacenamiento; "declaración" se refiere a los lugares donde se indica la naturaleza de la variable pero no se asigna almacenamiento. [pags. 33]
...
Es importante distinguir entre la declaración de una variable externa y su definición . Una declaración anuncia las propiedades de una variable (principalmente su tipo); una definición también hace que se guarde el almacenamiento. Si las lineas
int sp; double val[MAXVAL]
aparecen fuera de cualquier función, definen las variables externas
sp
yval
hacen que se guarde el almacenamiento, y también sirven como declaración para el resto del archivo fuente.Por otro lado, las lineas
extern int sp; extern double val[];
declaran para el resto del archivo fuente que
sp
es unint
y queval
es unadouble
matriz (cuyo tamaño se determina en otro lugar), pero no crean las variables ni reservan almacenamiento para ellos.Debe haber solo una definición de una variable externa entre todos los archivos que componen el programa fuente. ... Los tamaños de matriz deben especificarse con la definición, pero son opcionales con una
extern
declaración. [páginas. 80-81]...
Las declaraciones especifican la interpretación dada a cada identificador; no necesariamente reservan el almacenamiento asociado con el identificador. Las declaraciones que reservan almacenamiento se denominan definiciones . [pags. 210]
Declaración significa dar nombre y tipo a una variable (en caso de declaración de variable), por ejemplo:
int i;
o dar nombre, tipo de retorno y tipo de parámetro (s) a una función sin cuerpo (en caso de declaración de función), por ejemplo:
int max(int, int);
mientras que definición significa asignar valor a una variable (en caso de definición de variable), por ejemplo:
i = 20;
o proporcionar / agregar cuerpo (funcionalidad) a una función se denomina definición de función, por ejemplo:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
muchas declaraciones y definiciones de tiempo se pueden hacer juntas como:
int i=20;
y:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
En los casos anteriores definimos y declaramos variables i
y function max()
.
int x;