O significado de ambos me escapa.
O significado de ambos me escapa.
Respostas:
Uma declaração introduz um identificador e descreve seu tipo, seja um tipo, objeto ou função. Uma declaração é o que o compilador precisa para aceitar referências a esse identificador. Estas são declarações:
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
Uma definição realmente instancia / implementa esse identificador. É o que o vinculador precisa para vincular referências a essas entidades. Estas são definições correspondentes às declarações acima:
int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};
Uma definição pode ser usada no lugar de uma declaração.
Um identificador pode ser declarado quantas vezes você desejar. Portanto, o seguinte é legal em C e 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);
No entanto, ele deve ser definido exatamente uma vez. Se você esquecer de definir algo que foi declarado e referenciado em algum lugar, o vinculador não sabe ao que vincular referências e reclama sobre a falta de símbolos. Se você definir algo mais de uma vez, o vinculador não saberá a quais definições vincular referências e queixas sobre símbolos duplicados.
Como o debate sobre o que é uma declaração de classe versus uma definição de classe em C ++ continua aparecendo (em respostas e comentários para outras perguntas), colarei uma citação do padrão C ++ aqui.
Em 3.1 / 2, o C ++ 03 diz:
Uma declaração é uma definição, a menos que seja [...] uma declaração de nome de classe [...].
3.1 / 3 dá alguns exemplos. Dentre elas:
[Exemplo: [...] struct S {int a; int b; }; // define S, S :: ae S :: b [...] struct S; // declara S - por exemplo
Resumindo: O padrão C ++ considera struct x;
uma declaração e struct x {};
uma definição . (Em outras palavras, "declaração direta" é um nome impróprio , pois não há outras formas de declaração de classe em C ++.)
Agradecimentos a Litb (Johannes Schaub), que desenterrou o capítulo e o verso em uma de suas respostas.
extern int i
é uma declaração, uma vez que apenas introduz / especifica i
. Você pode ter quantos extern int i
em cada unidade de compilação quiser. int i
, no entanto, é uma definição. Denota o espaço para o número inteiro estar nesta unidade de conversão e aconselha o vinculador a vincular todas as referências a i
essa entidade. Se você tiver mais ou menos do que exatamente uma dessas definições, o vinculador irá reclamar.
int i;
no escopo arquivo / global ou escopo da função é uma definição tanto em C quanto em C ++. Em C, porque aloca armazenamento, e em C ++, porque não possui o especificador externo ou uma especificação de ligação. Isso equivale à mesma coisa, como diz o sbi: nos dois casos, esta declaração especifica o objeto ao qual todas as referências a "i" nesse escopo devem ser vinculadas.
struct A { double f(int, double); double f(int, double); };
inválido, é claro. É permitido em outro lugar embora. Há alguns lugares onde você pode declarar as coisas, mas não define, também: void f() { void g(); }
válido, mas não o seguinte: void f() { void g() { } };
. O que é uma definição e que declaração tem regras sutis quando se trata de modelos - cuidado! +1 para uma boa resposta.
Na seção 3.1 do padrão C ++:
Uma declaração introduz nomes em uma unidade de tradução ou redefine nomes introduzidos por declarações anteriores. Uma declaração especifica a interpretação e os atributos desses nomes.
O próximo parágrafo declara (ênfase minha) que uma declaração é uma definição, a menos que ...
... declara uma função sem especificar o corpo da função:
void sqrt(double); // declares sqrt
... declara um membro estático dentro de uma definição de classe:
struct X
{
int a; // defines a
static int b; // declares b
};
... declara um nome de classe:
class Y;
... contém a extern
palavra - chave sem um inicializador ou corpo de função:
extern const int i = 0; // defines i
extern int j; // declares j
extern "C"
{
void foo(); // declares foo
}
... ou é uma declaração typedef
ou using
.
typedef long LONG_32; // declares LONG_32
using namespace std; // declares std
Agora, pela grande razão pela qual é importante entender a diferença entre uma declaração e definição: a Regra de Uma Definição . Na seção 3.2.1 do padrão C ++:
Nenhuma unidade de tradução deve conter mais de uma definição de qualquer variável, função, tipo de classe, tipo de enumeração ou modelo.
struct x {static int b = 3; };
?
b
também seja declarada const
. Consulte stackoverflow.com/a/3536513/1858225 e daniweb.com/software-development/cpp/threads/140739/… .
Declaração: "Em algum lugar, existe um foo".
Definição: "... e aqui está!"
Existem casos interessantes em C ++ (alguns deles também em C). Considerar
T t;
Pode ser uma definição ou declaração, dependendo do tipo T
:
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".
No C ++, ao usar modelos, há outro caso de borda.
template <typename T>
struct X {
static int member; // declaration
};
template<typename T>
int X<T>::member; // definition
template<>
int X<bool>::member; // declaration!
A última declaração não era uma definição. É a declaração de uma especialização explícita do membro estático de X<bool>
. Ele diz ao compilador: "Se for para instanciar X<bool>::member
, não instancie a definição do membro a partir do modelo primário, mas use a definição encontrada em outro lugar". Para fazer uma definição, você precisa fornecer um inicializador
template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.
Declaração
As declarações informam ao compilador que existe um elemento ou nome de programa. Uma declaração introduz um ou mais nomes em um programa. As declarações podem ocorrer mais de uma vez em um programa. Portanto, classes, estruturas, tipos enumerados e outros tipos definidos pelo usuário podem ser declarados para cada unidade de compilação.
Definição
As definições especificam quais códigos ou dados o nome descreve. Um nome deve ser declarado antes de poder ser usado.
class foo {};
é uma definição de classe , não é?
Do padrão C99, 6,7 (5):
Uma declaração especifica a interpretação e os atributos de um conjunto de identificadores. Uma definição de um identificador é uma declaração para esse identificador que:
No padrão C ++, 3.1 (2):
Uma declaração é uma definição, a menos que declare uma função sem especificar o corpo da função, contenha o especificador externo ou uma especificação de ligação e nem um inicializador nem um corpo da função, declare um membro de dados estático em uma declaração de classe, é um declaração de nome de classe ou é uma declaração typedef, uma declaração de uso ou uma diretiva de uso.
Depois, existem alguns exemplos.
Tão interessante (ou não, mas estou um pouco surpreso com isso) typedef int myint;
é uma definição em C99, mas apenas uma declaração em C ++.
typedef
, isso não significa que ele pode ser repetido em C ++, mas não em C99?
Do wiki.answers.com:
O termo declaração significa (em C) que você está dizendo ao compilador sobre tipo, tamanho e, no caso de declaração de função, tipo e tamanho de seus parâmetros de qualquer variável ou tipo ou função definida pelo usuário em seu programa. Nenhum espaço é reservado na memória para qualquer variável em caso de declaração. No entanto, o compilador sabe quanto espaço reservar, caso uma variável desse tipo seja criada.
por exemplo, a seguir estão todas as declarações:
extern int a;
struct _tagExample { int a; int b; };
int myFunc (int a, int b);
A definição, por outro lado, significa que, além de tudo o que a declaração faz, o espaço também é reservado na memória. Você pode dizer "DEFINIÇÃO = DECLARAÇÃO + RESERVA DE ESPAÇO" a seguir são exemplos de definição:
int a;
int b = 0;
int myFunc (int a, int b) { return a + b; }
struct _tagExample example;
veja Respostas .
struct foo {};
é uma definição , não uma declaração. Uma declaração de foo
seria struct foo;
. A partir disso, o compilador não sabe quanto espaço reservar para os foo
objetos.
struct foo;
é uma declaração, mas não informa ao compilador o tamanho de foo. Eu acrescentaria que struct _tagExample { int a; int b; };
é uma definição. Portanto, neste contexto, é enganoso chamá-lo de declaração. Claro que é uma, já que todas as definições são declarações, mas você parece sugerir que não é uma definição. É uma definição de _tagExample.
Como não vejo uma resposta pertinente ao C ++ 11, aqui está uma.
Uma declaração é uma definição, 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 adicionais herdadas do C ++ 03 pela lista acima:
int add(int x, int y);
extern int a;
ouextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
using namespace NS;
Uma declaração de modelo é uma declaração. Uma declaração de modelo também é uma definição se sua declaração define uma função, uma classe ou um membro de dados estático.
Exemplos do padrão que diferencia entre declaração e definição que achei úteis para entender as nuances entre eles:
// 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
Definição:
extern int a; // Declaration
int a; // Definition
a = 10 // Initialization
int b = 10; // Definition & Initialization
A definição associa a variável a um tipo e aloca memória, enquanto a declaração apenas especifica o tipo, mas não aloca memória. A declaração é mais útil quando você deseja consultar a variável antes da definição.
* Não confunda definição com inicialização. Ambos são diferentes, a inicialização dá valor à variável. Veja o exemplo acima.
A seguir estão alguns exemplos de definição.
int a;
float b;
double c;
Agora , declaração de função:
int fun(int a,int b);
Observe o ponto-e-vírgula no final da função, por isso diz que é apenas uma declaração. O compilador sabe que em algum lugar do programa essa função será definida com esse protótipo. Agora, se o compilador receber uma chamada de função, algo como isto
int b=fun(x,y,z);
O compilador lançará um erro dizendo que não existe essa função. Porque ele não possui nenhum protótipo para essa função.
Observe a diferença entre dois programas.
Programa 1
#include <stdio.h>
void print(int a)
{
printf("%d",a);
}
main()
{
print(5);
}
Neste, a função de impressão é declarada e definida também. Como a chamada de função está vindo após a definição. Agora veja o 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);
}
É essencial porque a chamada de função precede a definição, portanto o compilador deve saber se existe alguma função. Então, declaramos a função que informará o compilador.
Definição:
Essa parte da definição de uma função é chamada de Definição. Diz o que fazer dentro da função.
void print(int a)
{
printf("%d",a);
}
int a; //declaration; a=10; //definition
Isso está completamente errado. Ao falar sobre objetos de duração de armazenamento automático (objetos declarados dentro de uma definição de função que não são declarados com outro especificador de classe de armazenamento como extern), essas são sempre definições.
Regra prática:
Uma declaração informa ao compilador como interpretar os dados da variável na memória. Isso é necessário para todo acesso.
Uma definição reserva a memória para tornar a variável existente. Isso precisa acontecer exatamente uma vez antes do primeiro acesso.
Para entender os substantivos, vamos nos concentrar primeiro nos verbos.
declarar - anunciar oficialmente; proclamar
define - para mostrar ou descrever (alguém ou algo) clara e completamente
Então, quando você declara algo, basta dizer o que é .
// declaration
int sum(int, int);
Essa linha declara uma função C chamada sum
que recebe dois argumentos do tipo int
e retorna an int
. No entanto, você não pode usá-lo ainda.
Quando você fornece como realmente funciona , essa é a definição.
// definition
int sum(int x, int y)
{
return x + y;
}
Para entender a diferença entre declaração e definição, precisamos ver o código do assembly:
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)
e isso é apenas definição:
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 você pode ver, nada muda.
A declaração é diferente da definição porque fornece informações usadas apenas pelo compilador. Por exemplo, uint8_t diz ao compilador para usar a função asm movb.
Veja que:
uint def; | no instructions
printf("some stuff..."); | [...] callq 0x400450 <printf@plt>
def=5; | movb $0x5,-0x45(%rbp)
A declaração não possui uma instrução equivalente, porque não é algo a ser executado.
Além disso, a declaração informa ao compilador o escopo da variável.
Podemos dizer que a declaração é uma informação usada pelo compilador para estabelecer o uso correto da variável e por quanto tempo alguma memória pertence a determinada variável.
Não foi possível declarar, nos termos mais gerais possíveis, que uma declaração é um identificador no qual nenhum armazenamento é alocado e uma definição realmente aloca armazenamento de um identificador declarado?
Um pensamento interessante - um modelo não pode alocar armazenamento até que a classe ou função esteja vinculada às informações de tipo. Então, o identificador de modelo é uma declaração ou definição? Deve ser uma declaração, já que nenhum armazenamento é alocado e você está simplesmente 'criando um protótipo' da classe ou função do modelo.
template<class T> struct foo;
é uma declaração de modelo , e assim é template<class T> void f();
. As definições de modelo espelham as definições de classe / função da mesma maneira. (Observe que o nome de um modelo não é um tipo ou nome de função . Um lugar onde você pode ver isso é quando não é possível transmitir um modelo como parâmetro de tipo de outro modelo. Se você deseja passar modelos em vez de tipos, precisa de parâmetros de modelo. )
Encontrar respostas semelhantes aqui: Perguntas entrevista técnica em C .
Uma declaração fornece um nome para o programa; uma definição fornece uma descrição exclusiva de uma entidade (por exemplo, tipo, instância e função) dentro do programa. As declarações podem ser repetidas em um determinado escopo; ele introduz um nome em um determinado escopo.
Uma declaração é uma definição, a menos que:
Uma definição é uma declaração, a menos que:
Isso vai parecer muito extravagante, mas é a melhor maneira de manter os termos em mente:
Declaração: Imagine Thomas Jefferson fazendo um discurso ... "DECLARO QUE ESTE FOO EXISTE NESTE CÓDIGO DE ORIGEM !!!"
Definição: imagine um dicionário, você está procurando Foo e o que realmente significa.
De acordo com o manual da biblioteca GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )
Em C, uma declaração apenas fornece informações de que uma função ou variável existe e fornece seu tipo. Para uma declaração de função, informações sobre os tipos de seus argumentos também podem ser fornecidas. O objetivo das declarações é permitir que o compilador processe corretamente as referências às variáveis e funções declaradas. Uma definição, por outro lado, na verdade aloca armazenamento para uma variável ou diz o que uma função faz.
O conceito de Declaração e Definição formará uma armadilha quando você estiver usando a classe de armazenamento externo, porque sua definição estará em outro local e você estará declarando a variável no seu arquivo de código local (página). Uma diferença entre C e C ++ é que, em C, as declarações são feitas normalmente no início de uma função ou página de código. Em C ++, não é assim. Você pode declarar em um local de sua escolha.
Meu exemplo favorito é "int Num = 5" aqui sua variável é 1. definida como int 2. declarada como Num e 3. instanciada com um valor de cinco. Nós
Uma classe ou estrutura permite alterar como os objetos serão definidos quando usados posteriormente. Por exemplo
Quando aprendemos a programar, esses dois termos geralmente são confundidos, porque geralmente fazemos as duas coisas ao mesmo tempo.
Etapas de uma geração executável:
(1) pré-processador -> (2) tradutor / compilador -> (3) vinculador
No estágio 2 (tradutor / compilador), as declarações de declaração em nosso código informam ao compilador que essas coisas vamos usar no futuro e você poderá encontrar a definição posteriormente, o que significa:
tradutor certifique-se de que: o que é o quê? significa declaração
e (3) estágio (vinculador) precisa de definição para vincular as coisas
O Linker garante: onde está o quê? significa definição
Existem algumas definições muito claras espalhadas por todo o K&R (2ª edição); ajuda colocá-los em um único lugar e lê-los como um:
"Definição" refere-se ao local onde a variável é criada ou atribuída armazenamento; "declaração" refere-se aos locais onde a natureza da variável é declarada, mas nenhum armazenamento é alocado. [p. 33]
...
É importante distinguir entre a declaração de uma variável externa e sua definição . Uma declaração anuncia as propriedades de uma variável (principalmente seu tipo); uma definição também faz com que o armazenamento seja reservado. Se as linhas
int sp; double val[MAXVAL]
aparecem fora de qualquer função, eles definem as variáveis externas
sp
eval
fazem com que o armazenamento seja separado e também servem como declaração para o restante desse arquivo de origem.Por outro lado, as linhas
extern int sp; extern double val[];
declare para o restante do arquivo de origem que
sp
éint
e queval
é umadouble
matriz (cujo tamanho é determinado em outro lugar), mas eles não criam as variáveis ou reservam armazenamento para elas.Deve haver apenas uma definição de variável externa entre todos os arquivos que compõem o programa de origem. ... Os tamanhos de matriz devem ser especificados com a definição, mas são opcionais com um
extern
declaração. [pp. 80-81]...
As declarações especificam a interpretação dada a cada identificador; eles não reservam necessariamente armazenamento associado ao identificador. As declarações que reservam armazenamento são chamadas de definições . [p. 210]
Declaração significa dar nome e tipo a uma variável (no caso de declaração de variável), por exemplo:
int i;
ou forneça o nome, digite o tipo de retorno e o tipo de parâmetro (s) para uma função sem corpo (no caso de declaração de função), por exemplo:
int max(int, int);
Considerando que definição significa atribuir valor a uma variável (no caso de definição de variável), por exemplo:
i = 20;
ou fornecer / adicionar corpo (funcionalidade) a uma função é chamado de definição de função, por exemplo:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
muitas declarações e definições de tempo podem ser feitas juntas como:
int i=20;
e:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
Nos casos acima, definimos e declaramos variáveis i
e function max()
.
int x;