Saya perhatikan bahwa jika saya mendeklarasikan variabel global beberapa kali, kompiler bahkan tidak mengeluarkan peringatan.
Namun jika saya mendeklarasikan variabel lokal dalam suatu fungsi beberapa kali, misalnya, kompiler gcc menghasilkan kesalahan dan tidak mengkompilasi file. (Saya bertanya dalam hal gcc, tapi ini lebih merupakan pertanyaan desain bahasa umum, bukan pertanyaan tentang gcc, karena saya pikir kemungkinan kompiler lain berperilaku serupa).
Apa penjelasan untuk perilaku ini?
extern int x;
, yang merupakan deklarasi, kompilasi akan dibatalkan karena tidak ada tempat di mana memori dialokasikan ke variabel.Jawaban:
Menurut pedoman pengkodean :
Variabel lokal tidak memiliki tautan. jadi ada nama Tabrakan terjadi. Jadi, beberapa deklarasi variabel lokal tidak mungkin.
Variabel global memiliki hubungan eksternal. Jadi, beberapa deklarasi variabel global dimungkinkan.
sumber
@msc memberikan pengantar yang baik tentang aturan di balik perilaku ini.
C memiliki tiga jenis deklarasi global untuk objek, yaitu yang (dan saya paham di
static
sini):extern int a;
int a = 3;
atauextern int a = 3;
int a;
Deklarasi berganda tipe 1 & 3 diizinkan, sementara paling banyak satu (tipe 2) definisi diizinkan.
Jika Anda juga bertanya tentang motivasi untuk aturan ini, itu adalah dukungan untuk kompilasi terpisah . (Lihat unit terjemahan ).
Untuk memecah suatu program menjadi beberapa file yang dikompilasi secara terpisah, kita memerlukan beberapa fitur, yaitu (a) dapat mendeklarasikan tanpa harus mendefinisikan , dan, (b) meneruskan deklarasi .
Dalam satu unit terjemahan, kami harus dapat merujuk ke fungsi global dan data dalam unit terjemahan lain. Dan kami juga ingin memeriksa kesalahan, di sini, untuk menemukan definisi yang hilang, dan definisi duplikat yang salah.
Terkadang, di unit terjemahan yang sama, kami mendeklarasikan global, dan kemudian mendefinisikannya nanti. Ini dapat terjadi jika kita memerlukan deklarasi maju untuk beberapa alasan, atau jika kita menggunakan file header umum (yang menyediakan deklarasi) dalam satu unit terjemahan yang juga menawarkan definisi eksplisit.
Karena kompilasi terpisah dalam C berlaku dengan menghubungkan fungsi dan data global bersama-sama, fitur-fitur ini diperlukan di tingkat global tetapi tidak di tingkat lokal.
Seperti yang ditunjukkan oleh @msc, semua ini tidak diperlukan untuk variabel lokal karena mereka tidak memiliki tautan.
C (seperti banyak bahasa lain) tidak menyediakan keterkaitan untuk variabel lokal karena bahasa tidak berusaha untuk mendukung fungsi tunggal yang mencakup beberapa unit terjemahan terpisah.
(Tentu saja, Anda dapat memiliki fungsi span beberapa file sumber, tetapi tidak beberapa unit terjemahan.)
Definisi tentatif berfungsi seperti deklarasi karena diizinkan dalam beberapa unit terjemahan (dan juga menggabungkan dengan baik dengan deklarasi lain). Namun, jika tidak ada definisi (non-tentatif) untuk pengidentifikasi di seluruh program, himpunan (satu atau lebih) definisi tentatif di beberapa unit terjemahan (untuk satu pengidentifikasi) diambil sebagai definisi untuk objek yang penginisialisasinya adalah nol.
Ini dapat diimplementasikan dengan menempatkan ini ke dalam bagian .BSS dengan ukuran dan keselarasan yang tepat; linker akan mencocokkannya dengan definisi sebenarnya jika ditemukan, atau mencocokkannya satu sama lain, memberi mereka ruang kosong di BSS.
Gagasan kompilasi yang terpisah dapat didukung sepenuhnya tanpa fitur definisi tentatif - Saya pikir definisi tentatif ada sebagian besar karena alasan historis. (Saya tidak mengatakan mereka tidak berguna, hanya jika bahasa itu dibuat hari ini, ini mungkin dianggap tidak perlu dan karenanya tidak ditawarkan.)
sumber