Arti dari keduanya menghindari saya.
Arti dari keduanya menghindari saya.
Jawaban:
Sebuah deklarasi memperkenalkan sebuah identifier dan menjelaskan jenisnya, baik itu jenis, objek, atau fungsi. Deklarasi adalah apa yang dibutuhkan kompiler untuk menerima referensi ke pengidentifikasi itu. Ini adalah deklarasi:
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
Sebuah definisi sebenarnya instantiates / alat pengenal ini. Itulah yang dibutuhkan penghubung untuk menautkan referensi ke entitas tersebut. Ini adalah definisi yang sesuai dengan deklarasi di atas:
int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};
Definisi dapat digunakan sebagai pengganti deklarasi.
Identifier dapat dideklarasikan sesering yang Anda inginkan. Dengan demikian, berikut ini legal di C dan 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);
Namun, harus didefinisikan tepat sekali. Jika Anda lupa mendefinisikan sesuatu yang telah dideklarasikan dan dirujuk di suatu tempat, maka linker tidak tahu harus menautkan referensi apa dan mengeluh tentang simbol yang hilang. Jika anda mendefinisikan sesuatu yang lebih dari sekali, maka linker tidak tahu mana dari definisi-link referensi ke dan mengeluh tentang simbol digandakan.
Karena debat apa yang merupakan deklarasi kelas vs definisi kelas dalam C ++ terus muncul (dalam jawaban dan komentar untuk pertanyaan lain), saya akan menempelkan kutipan dari standar C ++ di sini.
Pada 3.1 / 2, C ++ 03 mengatakan:
Deklarasi adalah definisi kecuali [[]] adalah deklarasi nama kelas [...].
3.1 / 3 kemudian memberikan beberapa contoh. Di antara mereka:
[Contoh: [...] struct S {int a; int b; }; // mendefinisikan S, S :: a, dan S :: b [...] struct S; // menyatakan S —Kirim contoh
Untuk jumlah itu: The C ++ standar menganggap struct x;
menjadi deklarasi dan struct x {};
sebuah definisi . (Dengan kata lain, "peneruskan deklarasi" keliru , karena tidak ada bentuk lain dari deklarasi kelas di C ++.)
Terima kasih kepada litb (Johannes Schaub) yang menggali pasal dan ayat yang sebenarnya dalam salah satu jawabannya.
extern int i
adalah deklarasi, karena hanya memperkenalkan / menetapkan i
. Anda dapat memiliki banyak extern int i
di setiap unit kompilasi yang Anda inginkan. int i
Namun, adalah definisi. Ini menunjukkan ruang untuk integer berada di unit terjemahan ini dan menyarankan linker untuk menautkan semua referensi i
terhadap entitas ini. Jika Anda memiliki lebih atau kurang dari salah satu definisi ini, penghubung akan mengeluh.
int i;
dalam ruang lingkup file / global atau fungsi adalah definisi baik dalam C dan C ++. Dalam C karena mengalokasikan penyimpanan, dan dalam C ++ karena tidak memiliki penentu eksternal atau spesifikasi-tautan. Ini sama dengan hal yang sama, yang dikatakan sbi: dalam kedua kasus deklarasi ini menentukan objek yang semua rujukannya ke "i" dalam lingkup itu harus dihubungkan.
struct A { double f(int, double); double f(int, double); };
tidak valid, tentu saja. Itu diizinkan di tempat lain. Ada beberapa tempat di mana Anda dapat menyatakan hal, tetapi tidak menentukan, terlalu: void f() { void g(); }
valid, tapi tidak berikut: void f() { void g() { } };
. Apa definisi dan apa deklarasi memiliki aturan halus ketika datang ke template - berhati-hatilah! +1 untuk jawaban yang bagus.
Dari bagian standar C ++ 3.1:
Sebuah deklarasi memperkenalkan nama menjadi unit terjemahan atau redeclares nama diperkenalkan oleh deklarasi sebelumnya. Deklarasi menentukan interpretasi dan atribut dari nama-nama ini.
Paragraf berikutnya menyatakan (penekanan saya) bahwa deklarasi adalah definisi kecuali ...
... itu mendeklarasikan suatu fungsi tanpa menentukan tubuh fungsi:
void sqrt(double); // declares sqrt
... itu menyatakan anggota statis dalam definisi kelas:
struct X
{
int a; // defines a
static int b; // declares b
};
... itu menyatakan nama kelas:
class Y;
... itu berisi extern
kata kunci tanpa inisialisasi atau badan fungsi:
extern const int i = 0; // defines i
extern int j; // declares j
extern "C"
{
void foo(); // declares foo
}
... atau a typedef
atauusing
pernyataan.
typedef long LONG_32; // declares LONG_32
using namespace std; // declares std
Sekarang untuk alasan besar mengapa penting untuk memahami perbedaan antara deklarasi dan definisi: the Aturan Satu Definisi . Dari bagian 3.2.1 dari standar C ++:
Tidak ada unit terjemahan yang memuat lebih dari satu definisi variabel, fungsi, tipe kelas, tipe enumerasi, atau templat.
struct x {static int b = 3; };
?
b
dinyatakan juga const
. Lihat stackoverflow.com/a/3536513/1858225 dan daniweb.com/software-development/cpp/threads/140739/… .
Deklarasi: "Di suatu tempat, ada foo."
Definisi: "... dan ini dia!"
Ada kasus tepi yang menarik di C ++ (beberapa di antaranya di C juga). Mempertimbangkan
T t;
Itu bisa berupa definisi atau deklarasi, tergantung pada jenisnya 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".
Di C ++, saat menggunakan templat, ada kasing lain.
template <typename T>
struct X {
static int member; // declaration
};
template<typename T>
int X<T>::member; // definition
template<>
int X<bool>::member; // declaration!
Deklarasi terakhir bukan definisi. Ini adalah deklarasi spesialisasi eksplisit dari anggota statis X<bool>
. Ia memberi tahu kompiler: "Jika menyangkut instantiasi X<bool>::member
, maka jangan instantiasi definisi anggota dari templat utama, tetapi gunakan definisi yang ditemukan di tempat lain". Untuk menjadikannya definisi, Anda harus menyediakan inisialisasi
template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.
Pernyataan
Deklarasi memberitahu kompiler bahwa elemen atau nama program ada. Deklarasi memperkenalkan satu atau lebih nama ke dalam suatu program. Deklarasi dapat terjadi lebih dari sekali dalam suatu program. Oleh karena itu, kelas, struktur, tipe enumerasi, dan tipe yang ditentukan pengguna lainnya dapat dideklarasikan untuk setiap unit kompilasi.
Definisi
Definisi menentukan kode atau data apa yang diuraikan namanya. Sebuah nama harus dideklarasikan sebelum dapat digunakan.
class foo {};
apakah definisi kelas , bukan?
Dari standar C99, 6.7 (5):
Deklarasi menentukan interpretasi dan atribut dari set pengidentifikasi. Sebuah definisi dari sebuah identifier adalah deklarasi identifier bahwa:
Dari standar C ++, 3.1 (2):
Deklarasi adalah definisi kecuali jika ia mendeklarasikan suatu fungsi tanpa menentukan tubuh fungsi, itu berisi penspesifikasi eksternal atau suatu keterkaitan-spesifikasi dan bukan suatu penginisialisasi atau suatu badan fungsi, ia mendeklarasikan anggota data statis dalam suatu deklarasi kelas, itu adalah suatu deklarasi nama kelas, atau itu adalah deklarasi typedef, deklarasi use, atau directive use.
Lalu ada beberapa contoh.
Sangat menarik (atau tidak, tapi saya sedikit terkejut olehnya), typedef int myint;
adalah definisi dalam C99, tetapi hanya deklarasi di C ++.
typedef
, bukankah itu berarti bisa diulang dalam C ++, tetapi tidak di C99?
Dari wiki.answers.com:
Istilah deklarasi berarti (dalam C) bahwa Anda memberi tahu kompiler tentang jenis, ukuran dan dalam hal deklarasi fungsi, jenis dan ukuran parameternya dari variabel apa pun, atau tipe atau fungsi yang ditentukan pengguna dalam program Anda. Tidak ada ruang yang disimpan dalam memori untuk variabel apa pun dalam hal deklarasi. Namun kompiler tahu berapa banyak ruang untuk cadangan jika variabel jenis ini dibuat.
misalnya, berikut ini semua deklarasi:
extern int a;
struct _tagExample { int a; int b; };
int myFunc (int a, int b);
Definisi di sisi lain berarti bahwa selain semua hal yang dilakukan deklarasi, ruang juga dicadangkan dalam memori. Anda dapat mengatakan "DEFINISI = DEKLARASI + PEMESANAN RUANG" berikut ini adalah contoh definisi:
int a;
int b = 0;
int myFunc (int a, int b) { return a + b; }
struct _tagExample example;
lihat Jawaban .
struct foo {};
adalah definisi , bukan deklarasi. Deklarasi foo
akan menjadi struct foo;
. Dari itu, kompiler tidak tahu berapa banyak ruang untuk memesan foo
objek.
struct foo;
adalah deklarasi, tetapi ia tidak memberi tahu kompiler ukuran foo. Saya akan menambahkan itu struct _tagExample { int a; int b; };
adalah definisi. Jadi dalam konteks ini menyesatkan menyebutnya deklarasi. Tentu saja itu satu, karena semua definisi adalah deklarasi, tetapi Anda tampaknya menyarankan bahwa itu bukan definisi. Ini adalah definisi, dari _tagExample.
Karena saya tidak melihat jawaban yang berkaitan dengan C ++ 11 di sini adalah satu.
Deklarasi adalah definisi kecuali jika mendeklarasikan 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!")
;
Klausa tambahan yang diwarisi dari C ++ 03 oleh daftar di atas:
int add(int x, int y);
extern int a;
atauextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
using namespace NS;
Deklarasi templat adalah deklarasi. Deklarasi templat juga merupakan definisi jika deklarasi mendefinisikan fungsi, kelas, atau anggota data statis.
Contoh dari standar yang membedakan antara deklarasi dan definisi yang menurut saya sangat membantu dalam memahami nuansa di antara mereka:
// 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
Definisi:
extern int a; // Declaration
int a; // Definition
a = 10 // Initialization
int b = 10; // Definition & Initialization
Definisi mengaitkan variabel dengan tipe dan mengalokasikan memori, sedangkan deklarasi hanya menentukan tipe tetapi tidak mengalokasikan memori. Deklarasi lebih berguna ketika Anda ingin merujuk variabel sebelum definisi.
* Jangan bingung definisi dengan inisialisasi. Keduanya berbeda, inisialisasi memberikan nilai pada variabel. Lihat contoh di atas.
Berikut ini adalah beberapa contoh definisi.
int a;
float b;
double c;
Sekarang deklarasi fungsi:
int fun(int a,int b);
Catat titik koma di akhir fungsi jadi dikatakan hanya deklarasi. Compiler tahu bahwa di suatu tempat di program, fungsi itu akan didefinisikan dengan prototipe itu. Sekarang jika kompiler mendapat panggilan fungsi sesuatu seperti ini
int b=fun(x,y,z);
Compiler akan melempar kesalahan yang mengatakan bahwa tidak ada fungsi seperti itu. Karena tidak memiliki prototipe untuk fungsi itu.
Perhatikan perbedaan antara dua program.
Program 1
#include <stdio.h>
void print(int a)
{
printf("%d",a);
}
main()
{
print(5);
}
Dalam hal ini, fungsi cetak dideklarasikan dan didefinisikan juga. Karena panggilan fungsi datang setelah definisi. Sekarang lihat program selanjutnya.
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);
}
Ini penting karena pemanggilan fungsi mendahului definisi sehingga kompiler harus tahu apakah ada fungsi tersebut. Jadi kami mendeklarasikan fungsi yang akan menginformasikan kompiler.
Definisi:
Bagian dari pendefinisian fungsi ini disebut Definisi. Ia mengatakan apa yang harus dilakukan di dalam fungsi.
void print(int a)
{
printf("%d",a);
}
int a; //declaration; a=10; //definition
Ini sepenuhnya salah. Ketika berbicara tentang objek durasi penyimpanan otomatis (objek dideklarasikan di dalam definisi fungsi yang tidak dideklarasikan dengan specifier kelas penyimpanan lain seperti extern) ini selalu definisi.
Aturan praktis:
Sebuah deklarasi memberitahu compiler bagaimana menafsirkan data variabel di memori. Ini diperlukan untuk setiap akses.
Sebuah definisi cadangan memori untuk membuat variabel yang ada. Ini harus terjadi tepat satu kali sebelum akses pertama.
Untuk memahami kata benda, mari kita fokus pada kata kerja terlebih dahulu.
menyatakan - untuk mengumumkan secara resmi; menyatakan
define - untuk menampilkan atau menggambarkan (seseorang atau sesuatu) dengan jelas dan lengkap
Jadi, ketika Anda mendeklarasikan sesuatu, Anda hanya mengatakan apa itu .
// declaration
int sum(int, int);
Baris ini mendeklarasikan fungsi C yang dipanggil sum
yang mengambil dua argumen tipe int
dan mengembalikan sebuah int
. Namun, Anda belum dapat menggunakannya.
Ketika Anda memberikan cara kerjanya sebenarnya , itulah definisi untuk itu.
// definition
int sum(int x, int y)
{
return x + y;
}
Untuk memahami perbedaan antara deklarasi dan definisi, kita perlu melihat kode 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)
dan ini hanya definisi:
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)
Seperti yang Anda lihat tidak ada yang berubah.
Deklarasi berbeda dari definisi karena memberikan informasi yang hanya digunakan oleh kompiler. Sebagai contoh, uint8_t memberitahu kompiler untuk menggunakan asm function movb.
Lihat itu:
uint def; | no instructions
printf("some stuff..."); | [...] callq 0x400450 <printf@plt>
def=5; | movb $0x5,-0x45(%rbp)
Deklarasi tidak memiliki instruksi yang setara karena tidak ada sesuatu yang harus dieksekusi.
Lebih jauh deklarasi memberitahu kompiler lingkup variabel.
Kita dapat mengatakan bahwa deklarasi adalah informasi yang digunakan oleh kompiler untuk menetapkan penggunaan variabel yang benar dan untuk berapa lama sebagian memori dimiliki oleh variabel tertentu.
Tidak bisakah Anda menyatakan dengan syarat yang paling umum, bahwa deklarasi adalah pengidentifikasi di mana tidak ada penyimpanan yang dialokasikan dan definisi sebenarnya mengalokasikan penyimpanan dari pengidentifikasi yang dinyatakan?
Satu pemikiran menarik - templat tidak dapat mengalokasikan penyimpanan sampai kelas atau fungsi dikaitkan dengan informasi jenis. Jadi apakah pengidentifikasi templat merupakan deklarasi atau definisi? Ini harus berupa deklarasi karena tidak ada penyimpanan yang dialokasikan, dan Anda hanya 'membuat prototip' kelas templat atau fungsi.
template<class T> struct foo;
adalah deklarasi templat , dan begitu juga ini template<class T> void f();
. Definisi template mencerminkan definisi kelas / fungsi dengan cara yang sama. (Perhatikan bahwa nama templat bukan jenis atau nama fungsi . Satu tempat di mana Anda dapat melihat ini adalah ketika Anda tidak dapat meneruskan templat sebagai parameter jenis templat lainnya. Jika Anda ingin meneruskan templat alih-alih jenis, Anda memerlukan parameter templat templat. )
Temukan jawaban serupa di sini: Teknis Pertanyaan Wawancara di C .
Sebuah deklarasi menyediakan nama untuk program; sebuah definisi memberikan deskripsi unik tentang suatu entitas (misalnya tipe, instance, dan fungsi) dalam program. Deklarasi dapat diulang dalam lingkup yang diberikan, itu memperkenalkan nama dalam lingkup yang diberikan.
Deklarasi adalah definisi kecuali:
Definisi adalah deklarasi kecuali:
Ini kedengarannya benar-benar murahan, tetapi ini adalah cara terbaik saya dapat menjaga istilah-istilah itu tetap di kepala saya:
Deklarasi: Gambar Thomas Jefferson memberikan pidato ... "SAYA SUDAH MENYATAKAN BAHWA FOO INI ADA DI KODE SUMBER INI !!!"
Definisi: gambar sebuah kamus, Anda mencari Foo dan apa artinya sebenarnya.
Menurut manual pustaka GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )
Dalam C, deklarasi hanya menyediakan informasi bahwa ada fungsi atau variabel dan memberikan tipenya. Untuk deklarasi fungsi, informasi tentang jenis argumennya dapat diberikan juga. Tujuan dari deklarasi adalah untuk memungkinkan kompiler untuk memproses referensi ke variabel dan fungsi yang dideklarasikan dengan benar. Definisi, di sisi lain, sebenarnya mengalokasikan penyimpanan untuk variabel atau mengatakan apa fungsi tidak.
Konsep Deklarasi dan Definisi akan membentuk jebakan ketika Anda menggunakan kelas penyimpanan eksternal karena definisi Anda akan berada di beberapa lokasi lain dan Anda mendeklarasikan variabel dalam file kode lokal Anda (halaman). Satu perbedaan antara C dan C ++ adalah bahwa dalam C Anda deklarasi dilakukan secara normal pada awal halaman fungsi atau kode. Dalam C ++ tidak seperti itu. Anda dapat mendeklarasikan di tempat pilihan Anda.
Contoh favorit saya adalah "int Num = 5" di sini variabel Anda 1. didefinisikan sebagai int 2. dinyatakan sebagai Num dan 3. instantiated dengan nilai lima. Kita
Kelas atau struct memungkinkan Anda untuk mengubah bagaimana objek akan didefinisikan ketika nanti digunakan. Sebagai contoh
Ketika kita belajar pemrograman, kedua istilah ini sering membingungkan karena kita sering melakukan keduanya secara bersamaan.
Tahapan dari generasi yang dapat dieksekusi:
(1) pra-prosesor -> (2) penerjemah / kompiler -> (3) tautan
Pada tahap 2 (penerjemah / kompiler), pernyataan deklarasi dalam kode kita memberi tahu kompiler bahwa hal-hal ini akan kita gunakan di masa depan dan Anda dapat menemukan definisi nanti, artinya adalah:
penerjemah memastikan bahwa: apa itu apa? berarti deklarasi
dan (3) tahap (penghubung) perlu definisi untuk mengikat hal-hal
Linker memastikan bahwa: di mana ada apa? berarti definisi
Ada beberapa definisi yang sangat jelas ditaburkan di seluruh K&R (edisi ke-2); membantu menempatkan mereka di satu tempat dan membacanya sebagai satu:
"Definisi" mengacu pada tempat di mana variabel dibuat atau ditugaskan penyimpanan; "deklarasi" mengacu pada tempat-tempat di mana sifat variabel dinyatakan tetapi tidak ada penyimpanan yang dialokasikan. [hal. 33]
...
Penting untuk membedakan antara deklarasi variabel eksternal dan definisinya . Deklarasi mengumumkan properti variabel (terutama tipenya); definisi juga menyebabkan penyimpanan dikesampingkan. Jika garis
int sp; double val[MAXVAL]
muncul di luar fungsi apa pun, mereka menentukan variabel eksternal
sp
danval
, menyebabkan penyimpanan disingkirkan, dan juga berfungsi sebagai deklarasi untuk sisa file sumber itu.Di sisi lain, garis
extern int sp; extern double val[];
mendeklarasikan untuk sisa file sumber yang
sp
merupakanint
dan ituval
adalahdouble
array (yang ukurannya ditentukan di tempat lain), tetapi mereka tidak membuat variabel atau menyimpan cadangan untuk mereka.Hanya boleh ada satu definisi variabel eksternal di antara semua file yang membentuk program sumber. ... Ukuran array harus ditentukan dengan definisi, tetapi opsional dengan
extern
deklarasi. [hlm. 80-81]...
Deklarasi menentukan interpretasi yang diberikan kepada masing-masing pengidentifikasi; mereka tidak perlu menyimpan penyimpanan yang terkait dengan pengidentifikasi. Deklarasi bahwa penyimpanan cadangan disebut definisi . [hal. 210]
Deklarasi berarti memberi nama dan jenis ke variabel (dalam hal deklarasi variabel), misalnya:
int i;
atau berikan nama, jenis kembali dan jenis parameter ke fungsi tanpa badan (dalam hal deklarasi fungsi), misalnya:
int max(int, int);
sedangkan definisi berarti memberikan nilai ke variabel (dalam hal definisi variabel), misalnya:
i = 20;
atau menyediakan / menambah isi (fungsi) ke suatu fungsi disebut definisi fungsi, misalnya:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
banyak deklarasi dan definisi waktu dapat dilakukan bersama sebagai:
int i=20;
dan:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
Dalam kasus di atas kami mendefinisikan dan mendeklarasikan variabel i
dan function max()
.
int x;