it-swarm-tr.com

Bir tanım ile beyan arasındaki fark nedir?

İkisinin de anlamı beni rahatsız ediyor.

769
Maciek

Bir bildirim bir tanımlayıcı tanıtır ve türünü, bir tür, nesne veya işlev olarak tanımlar. Bir bildirim, bu tanımlayıcıya referansları kabul etmek için derleyicinin ihtiyaç duyduğu şeklindedir. Bunlar beyanlar: 

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

Bir tanım aslında bu tanımlayıcıyı başlatır/uygular. Referansları bu varlıklara bağlamak için bağlantının ihtiyacı olan. Bunlar yukarıdaki beyanlara karşılık gelen tanımlardır: 

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

Bir beyan yerine bir tanım kullanılabilir. 

Bir tanımlayıcı istediğiniz kadar sık ​​beyan edildi olabilir. Bu nedenle, aşağıdakiler C ve C++ ile yasaldır: 

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

Ancak, tam olarak bir kez tanımlı olmalıdır. Bildirilen ve bir yere başvuruda bulunulan bir şeyi tanımlamayı unutursanız, bağlayıcı, referansları neyle ilişkilendireceğini ve eksik sembollerle ilgili şikayetleri bilmez. Birden fazla şeyi bir şey tanımladıysanız, bağlayıcı, kopyalanan sembollerle ilgili referansları ve şikâyetleri tanımlamak için hangi ifadesini bilmez. 


C++ sınıfının ne olduğu tartışması bildirim'e karşı bir sınıf tanım, C++ 'a gelmeye devam ediyor (diğer soruların cevaplarında ve yorumlarında), C++ standardından alıntı yapıyorum İşte.
3.1/2'de, C++ 03 şöyle diyor:

Deklarasyon, [...] bir sınıf adı beyanı [...] olmadığı sürece bir tanımdır.

3.1/3 daha sonra birkaç örnek verir. Aralarında:

 [Örnek: [...] 
 Struct S {int a; int b; }; // S, S :: a ve S :: b [...] 
 struct S; // S 
 end örneğini ilan etti.

Özetlemek gerekirse: C++ standardı struct x; 'yu bildirim ve struct x {}; a tanım olarak kabul eder. (Başka bir deyişle, "yanlış beyanda" ileriye dönük beyanname} _, çünkü C++ 'da başka sınıf beyanı yoktur.) 

litb (Johannes Schaub) sayesinde asıl bölümü çıkarmış ve cevaplarından bir tanesini çıkarmış. 

782
sbi

C++ standart bölümünden 3.1:

Bir bildirim, bir çeviri birimine isimler getirir ya da önceki .__ tarafından girilen isimleri redeler. beyanları. Bir bildiri, bu isimlerin yorumlanmasını ve niteliklerini belirtir.

Bir sonraki paragraf, (benimkine vurgu yapar) beyanatın bir tanım olduğunu.

... işlev gövdesini belirtmeden bir işlev bildirir

void sqrt(double);  // declares sqrt

... sınıf tanımında statik bir üye olduğunu bildirir

struct X
{
    int a;         // defines a
    static int b;  // declares b
};

... sınıf adı bildirir

class Y;

... bir başlatıcı veya işlev gövdesi olmadan extern anahtar sözcüğünü içerir

extern const int i = 0;  // defines i
extern int j;  // declares j
extern "C"
{
    void foo();  // declares foo
}

... veya bir typedef veya using deyimidir.

typedef long LONG_32;  // declares LONG_32
using namespace std;   // declares std

Şimdi, bildiri ile tanım arasındaki farkı anlamak neden önemli bir nedenden dolayı: One Definition Rule. C++ standardının 3.2.1 bölümünden:

Hiçbir çeviri birimi, değişken, işlev, sınıf türü, numaralandırma türü veya şablon için birden fazla tanım içermemelidir.

162

Deklarasyon: "Bir yerlerde bir foo var."

Tanımı: "... işte burda!"

125
plinth

C++ 'da ilginç Edge vakaları var (bir kısmı da C de). Düşünmek

T t;

T türünün türüne bağlı olarak, bu bir tanım veya bildirim olabilir:

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".

C++ 'da şablon kullanırken, başka bir Edge durumu var. 

template <typename T>
struct X { 
  static int member; // declaration
};

template<typename T>
int X<T>::member; // definition

template<>
int X<bool>::member; // declaration!

Son bildirim, değil bir tanımdı. X<bool> statik üyesinin özel bir uzmanlık bildirimidir. Derleyiciye şunları söyler: "X<bool>::member örneğini somutlaştırmak söz konusu ise, üyenin tanımını birincil şablondan başlatmayın, başka yerde bulunan tanımı kullanın". Bir tanım yapmak için, bir başlatıcı sağlamanız gerekir

template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.
44

Beyan

Bildiriler derleyiciye a program elemanı veya ismi var. Bir beyan bir veya daha fazla .__ tanıtır. bir programa isimler verir. Beyanname olabilir. bir programda bir kereden fazla ortaya çıkar . Bu nedenle, sınıflar, yapılar, numaralandırılmış türleri ve diğer kullanıcı tanımlı türler için bildirilebilir. Her derleme birimi.

Tanım

Tanımlar hangi kodu veya verileri belirtir. adı açıklar. Bir isim olmalı. kullanmadan önce bildirildi.

31
adatapost

C99 standardından, 6.7 (5):

Bir bildirim, bir tanımlayıcı grubunun yorumlanmasını ve niteliklerini belirtir. Bir tanımlayıcıya ait A tanımı , bu tanımlayıcıya ilişkin bir bildirimdir:

  • bir nesne için, depolamanın o nesne için ayrılmasına neden olur;
  • bir işlev için, işlev gövdesini içerir;
  • bir numaralandırma sabiti veya typedef ismi için, tanımlayıcısının (sadece) beyanıdır.

C++ standardından 3.1 (2):

Beyanname, tanım işlevidir, fonksiyonun gövdesini belirtmeden bir işlev ilan etmezse, harici bir belirtici veya bir bağlantı belirtimi içerir ve ne başlatıcı ne de işlev gövdesi içermez, sınıf bildirgesinde statik bir veri üyesi bildirir , bu bir sınıf adı bildirimidir veya bir typedef bildirimi, bir kullanım-beyanı veya bir kullanma-yönergesidir.

O zaman bazı örnekler var.

Çok ilginç (ya da değil, ama biraz şaşırdım), typedef int myint;, C99'daki bir tanımdır, ancak yalnızca C++ dilinde bir bildirimdir.

20
Steve Jessop

Wiki.answers.com adresinden:

Beyanname terimi (C cinsinden), derleyiciye programınızdaki herhangi bir değişkene ait değişkenlerin türlerini, büyüklüklerini ve işlev bildirimlerini, türlerini ve boyutlarını veya kullanıcı tanımlı tür veya işlevlerini anlattığınız anlamına gelir. Hayır bildirim durumunda herhangi bir değişken için bellekte yer ayrılır. Bununla birlikte, derleyici bu tür bir değişkenin yaratılması durumunda ne kadar yer ayrılacağını bilir.

örneğin, aşağıdaki tüm bildirimler şunlardır: 

extern int a; 
struct _tagExample { int a; int b; }; 
int myFunc (int a, int b);

Öte yandan, tanımlamanın yaptığı her şeye ilaveten, alanın da bellekte saklandığı anlamına gelir. Aşağıdaki "TANIM = BİLDİRİM + UZAY REZERVASYONU" diyebilirsiniz: 

int a; 
int b = 0; 
int myFunc (int a, int b) { return a + b; } 
struct _tagExample example; 

bkz. Cevaplar .

14
Marcin Gil

C++ 11 Güncellemesi

C++ 11 ile ilgili bir cevap göremediğim için işte bir tane.

Bir bildirim a tanım ise//

  • opak enum - enum X : int;
  • şablon parametresi -T'in template<typename T> class MyArray;
  • parametre bildirimi - x ve y / int add(int x, int y);
  • takma ad bildirimi - using IntVector = std::vector<int>;
  • statik assert bildirimi - static_assert(sizeof(int) == 4, "Yikes!")
  • özellik bildirimi (uygulama tanımlı)
  • boş bildirim ;

Yukarıdaki listeye göre C++ 03'ten devralınan başka hükümler:

  • işlev bildirimi - add in int add(int x, int y);
  • bildirimi veya bağlantı belirticisini içeren harici belirtici - extern int a; veya extern "C" { ... };
  • bir sınıftaki statik veri üyesi - x içinde class C { static int x; };
  • sınıf/yapı bildirimi - struct Point;
  • typedef bildirimi - typedef int Int;
  • bildirim kullanarak - using std::cout;
  • direktifini kullanarak - using namespace NS;

Bir şablon bildirimi bir bildiridir. Bir şablon bildirimi ayrıca, bildirimi bir işlevi, bir sınıfı veya statik bir veri üyesini tanımlarsa bir tanımdır.

Aralarındaki nüansları anlamada yardımcı bulduğum beyan ve tanım arasında ayrım yapan standarttan örnekler:

// 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
12
legends2k

Beyan:  

int a; // this declares the variable 'a' which is of type 'int'

Böylece bildirim, değişkeni bir türle ilişkilendirir.

Aşağıda bazı beyan örnekleri verilmiştir.

int a;
float b;
double c;

Şimdi işlev bildirimi:

int fun(int a,int b); 

İşlev sonundaki noktalı virgül notunu not edin, böylece yalnızca bir bildirim olduğunu söyler. Derleyici programda bir yerde bu işlevin bu prototip ile tanımlı olacağını bilmektedir. Şimdi derleyici bir işlev görürse böyle bir şey çağırın 

int b=fun(x,y,z);

Derleyici böyle bir işlev olmadığını söyleyerek bir hata atar. Çünkü bu fonksiyon için herhangi bir prototip yok.

İki program arasındaki farkı not edin.

Program 1

#include <stdio.h>
void print(int a)
{
     printf("%d",a);
}
main()
{
    print(5);
}

Bu durumda, yazdırma işlevi de bildirilir ve tanımlanır. Fonksiyon çağrısı tanımdan sonra geldiğinden beri. Şimdi bir sonraki programa bakın.

Program 2

 #include <stdio.h>
 void print(int a); // In this case this is essential
 main()
 {
    print(5);
 }
 void print(int a)
 {
     printf("%d",a);
 }

İşlev çağrısı tanımdan önce olduğundan çok önemlidir, bu nedenle derleyici böyle bir işlevin olup olmadığını bilmelidir. Böylece derleyiciyi bilgilendirecek olan işlevi ilan ediyoruz.

Tanım :  

Bir işlevi tanımlamanın bu bölümüne Tanım denir. Fonksiyonun içinde ne yapılması gerektiğini söylüyor. 

void print(int a)
{
    printf("%d",a);
}

Şimdi değişkenlerle.

int a; //declaration
a=10; //definition 

Bazı zamanlar beyan ve tanım bunun gibi tek bir ifadede gruplandırılır.

int a=10;
4
Sridharan

tanım, asıl işlev yazılan anlamına gelir ve bildirim, örneğin basit işlev bildirimi anlamına gelir. 

void  myfunction(); //this is simple declaration

ve 

void myfunction()
{
 some statement;    
}

bu işlev tanımı myfunction 

4
user565367

İsimleri anlamak için, önce fiillere odaklanalım.

ilan - resmen ilan etmek; ilan etmek

define - (açıkça veya tamamen) açıkça veya tamamen göstermek veya tarif etmek

Yani, bir şey ilan ettiğinizde, sadece ne olduğunu.

// declaration
int sum(int, int);

Bu satır bildirirsum adında bir c işlevi, int türünde iki argüman alan ve bir int döndüren bir C işlevi. Ancak, henüz kullanamazsınız.

Gerçekte nasıl çalıştığı öğesini verdiğinizde, bunun tanımı budur.

// definition
int sum(int x, int y)
{
    return x + y;
}
3
Karoly Nyisztor

Başparmak kuralı:

  • A bildirimi , derleyiciye, değişken verisinin hafızasında nasıl yorumlanacağını söyler. Her erişim için bu gereklidir.

  • A definition , değişkeni var yapmak için belleği saklar. Bu ilk erişimden önce tam olarak bir kez gerçekleşmelidir.

3
bjhend

Burada benzer cevapları bulun: C Teknik Röportaj Sorular .

A bildirimi programa bir ad sağlar; a tanımı , programdaki bir öğenin (örneğin, tür, örnek ve işlev) benzersiz bir açıklamasını sağlar. Bildirimler verilen bir kapsamda tekrarlanabilir, verilen bir kapsamda bir isim verilir.

Bir bildirim:

  • Deklarasyon, vücudunu belirtmeden bir işlev ilan eder
  • Beyanda harici bir belirleyici var, başlatıcı veya işlev gövdesi yok,
  • Deklarasyon, sınıf tanımı olmayan statik sınıf veri üyesinin beyanıdır,
  • Deklarasyon bir sınıf ismi tanımıdır,

Bir tanım, aşağıdaki durumlar haricinde bir beyandır:

  • Tanım statik sınıf veri üyesini tanımlar.
  • Tanım, satır içi olmayan üye işlevini tanımlar.
2
Santosh

Mümkün olan en genel terimlerle, bir bildirimin, hiçbir depolama alanının ayrılmadığı ve bir tanımlamanın, bildirilen bir tanımlayıcıdan depolama ayırdığı bir tanımlayıcı olduğunu söyleyemez misiniz? 

İlginç bir düşünce - bir şablon, sınıf ya da fonksiyon, tip bilgisine bağlanana kadar depolama alanı tahsis edemez. Öyleyse, şablon tanımlayıcısı bir beyan mı yoksa tanım mı? Depolama alanı tahsis edilmediğinden bu bir bildirim olmalıdır ve siz sadece şablon sınıfını veya işlevi 'prototiplersiniz'.

2
user154171

Beyan ve tanım arasındaki farkı anlamak için Meclis kodunu görmemiz gerekir:

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)

ve bu sadece tanım:

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)

Gördüğünüz gibi hiçbir şey değişmiyor.

Beyanname tanımdan farklıdır çünkü sadece derleyici tarafından kullanılan bilgileri verir. Örneğin, uint8_t derleyiciye asm işlev movb kullanmasını söyler.

Şuna bakın:

uint def;                  |  no instructions
printf("some stuff...");   |  [...] callq   0x400450 <[email protected]>
def=5;                     |  movb    $0x5,-0x45(%rbp)

Deklarasyonun eşdeğeri bir talimatı yoktur çünkü yürütülmesi gereken bir şey değildir.

Ayrıca bildirim, derleyiciye değişkenin kapsamını bildirir.

Deklarasyonun, derleyicinin değişkenin doğru kullanımını ve bir belleğin ne kadar süreyle belirli bir değişkene ait olduğunu belirlemek için kullandığı bir bilgi olduğunu söyleyebiliriz.

2
princio

Beyanname, bir değişkene isim ve tür vermek anlamına gelir (değişken bildirimi durumunda). 

 int i;  

ya da isim, geri dönüş tipi ve parametre (ler) tipi, gövdesi olmayan bir fonksiyona verin (fonksiyon bildirimi durumunda)

Örneğin: 

int max(int, int);

tanım aracı ise bir değişkene değer atamak (değişken tanımı durumunda) .

i = 20;

veya bir işlev için gövde (işlevsellik) sağlamak/eklemek işlev tanımına denir.

Örneğin: 

 int max(int a, int b)
 {
    if(a>b)   return a;
    return b;  
 }

birçok zaman beyanı ve tanımı şu şekilde yapılabilir:

int i=20;   

ve

int max(int a, int b)
{
    if(a>b)   return a;
    return b;    
} 

Yukarıdaki durumlarda i ve function max () değişkenlerini tanımlayıp bildiririz.

1
Puneet Purohit

Bu gerçekten sevimsiz geliyor, ama terimleri aklımda tutmanın en iyi yolu bu:

Deklarasyon: Resim Thomas Jefferson’un bir konuşması ... "BU KAYNAK’IN BU KAYNAK KODUNDA OLDUĞUNDAN BELİRTİM!"

Tanım: bir sözlük çizin, Foo'yu ve gerçekte ne anlama geldiğini araştırıyorsunuz.

1
It'sPete

GNU C kütüphane kılavuzuna göre ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )

C'de, bildirim yalnızca bir işlev veya değişkenin var olduğu bilgisini verir ve türünü verir. Bir fonksiyon bildirimi için, argümanlarının tipleri hakkında da bilgi verilebilir. Bildirimlerin amacı, derleyicinin bildirilen değişkenlere ve işlevlere yapılan başvuruları doğru şekilde işlemesini sağlamaktır. Öte yandan, bir tanım aslında bir değişken için depolama alanı tahsis eder veya bir fonksiyonun ne yaptığını söyler.

1
LinuxBabe

Bir bildiri derleyiciye bir sembol ismi sunar. Tanım, sembol için yer ayıran bir bildiridir.

int f(int x); // function declaration (I know f exists)

int f(int x) { return 2*x; } // declaration and definition
0
hdante

Yürütülebilir bir neslin aşamaları: 

(1) ön işlemci -> (2) tercüman/derleyici -> (3) linker

2. aşamada (tercüman/derleyici), kodumuzdaki beyan ifadeleri derleyiciye gelecekte kullanacağımız bu şeyleri ve daha sonra tanımları bulabileceğinizi söyler:

çevirmen şunlardan emin olun: nedir? beyanname anlamına gelir 

ve (3) Aşama (linker) olayları bağlamak için tanımlamaya ihtiyaç duyar 

Linker şunlardan emin olun: nerede? tanım anlamına gelir

0
Jeet Parikh

K & R'ye serpiştirilmiş bazı çok net tanımlar var (2. baskı); onları bir yere koymaya ve onları tek olarak okumanıza yardımcı olur:

"Tanım", değişkenin oluşturulduğu veya atandığı depolama alanını ifade eder; "bildirim", değişkenin niteliğinin belirtildiği ancak depolama yeri tahsis edilmeyen yerleri ifade eder. [S. 33]

...

Harici bir değişkenin bildirisi ile tanımı arasındaki farkı ayırt etmek önemlidir. Bir bildiri, bir değişkenin özelliklerini (öncelikle türünü) ilan eder; Bir tanım aynı zamanda depolamanın bir kenara bırakılmasına neden olur. Eğer çizgiler

int sp;
double val[MAXVAL]

herhangi bir işlevin dışında görünürler, bunlar tanımla harici değişkenler sp ve val, depolamanın bir kenara bırakılmasına neden olur ve ayrıca bu kaynak dosyanın geri kalan kısmı için beyan olur. .

Öte yandan, çizgiler

extern int sp;
extern double val[];

declaresp bir int olan ve val bir double dizisi olan (_ başka boyutta belirlenir) kaynak dosyasının geri kalanı için , ancak değişkenler oluşturmazlar veya onlar için rezerv depolama yapmazlar.

Kaynak programı oluşturan tüm dosyalar arasında yalnızca bir tanım harici değişken olmalıdır. ... Dizi boyutları tanımla belirtilmelidir, ancak extern bildirimi ile isteğe bağlıdır. [S. 80-81]

...

Bildirimler, her bir tanımlayıcıya verilen yorumu belirtir; tanımlayıcıyla ilişkili depolamayı zorunlu olarak ayırmazlar. Depolamaya ilişkin bildirimlere tanımlar adı verilir. [S. 210]

0
Brad Solomon

En sevdiğim örnek "int Num = 5" burada değişkeniniz 1'dir. İnt olarak tanımlanmıştır 2. Num ve 3 olarak ifade edilmiştir. Biz

  • Yerleşik veya sınıf veya yapı olabilecek bir nesnenin türünü tanımlayın.
  • Bir nesnenin adını bildirin, böylece Değişkenler, İşlevler, vb. İçeren bir ismin bulunduğu bir şey ilan edildi.

Bir sınıf veya yapı, daha sonra kullanıldığında nesnelerin nasıl tanımlanacağını değiştirmenize izin verir. Örneğin

  • Biri özel olarak tanımlanmamış bir heterojen değişken veya dizi bildirebilir.
  • C++ 'daki bir ofset kullanarak, bildirilmiş bir adı olmayan bir nesne tanımlayabilirsiniz.

Programlamayı öğrendiğimizde, bu iki terim genellikle karışıktır, çünkü ikisini de aynı anda yaparız. 

0
Jason K.

Beyan ve Tanım kavramı, harici depolama sınıfını kullanırken, tanımınız başka bir yerde olacağından ve değişkeni yerel kod dosyanızda (sayfa) bildirdiğiniz için bir engel oluşturacaktır. C ve C++ arasındaki bir fark, C'de bildirimlerin normal olarak bir işlev veya kod sayfasının başlangıcında yapılmasıdır. C++ 'da öyle değil. İstediğiniz bir yerde ilan edebilirsiniz.

0
achoora