Di C, saya tidak melihat adanya pengaruh extern
kata kunci yang digunakan sebelum deklarasi fungsi. Pada awalnya, saya berpikir bahwa ketika mendefinisikan extern int f();
dalam satu file memaksa Anda untuk mengimplementasikannya di luar ruang lingkup file. Namun saya menemukan bahwa keduanya:
extern int f();
int f() {return 0;}
dan
extern int f() {return 0;}
kompilasi saja, tanpa peringatan dari gcc. Saya menggunakan gcc -Wall -ansi
; bahkan tidak mau menerima //
komentar.
Apakah ada efek untuk menggunakan extern
sebelum definisi fungsi ? Atau itu hanya kata kunci opsional tanpa efek samping untuk fungsi.
Dalam kasus terakhir saya tidak mengerti mengapa perancang standar memilih untuk mengotori tata bahasa dengan kata kunci berlebihan.
EDIT: Untuk memperjelas, saya tahu ada penggunaan untuk extern
variabel, tapi aku hanya bertanya tentang extern
di fungsi .
Jawaban:
Kami memiliki dua file, foo.c dan bar.c.
Ini foo.c
Sekarang, ini bar.c
Seperti yang Anda lihat, kami tidak memiliki tajuk bersama antara foo.c dan bar.c, namun bar.c membutuhkan sesuatu yang dideklarasikan di foo.c ketika terhubung, dan foo.c membutuhkan fungsi dari bar.c ketika terhubung.
Dengan menggunakan 'extern', Anda memberi tahu kompiler bahwa apa pun yang mengikutinya akan ditemukan (non-statis) pada waktu tautan; jangan mencadangkan apa pun untuknya di pass saat ini karena akan ditemui nanti. Fungsi dan variabel diperlakukan sama dalam hal ini.
Ini sangat berguna jika Anda perlu berbagi beberapa global antar modul dan tidak ingin meletakkan / menginisialisasi dalam header.
Secara teknis, setiap fungsi dalam tajuk publik pustaka adalah 'eksternal', namun memberi labelnya sangat sedikit atau tidak bermanfaat, tergantung pada kompilernya. Kebanyakan kompiler dapat mengetahuinya sendiri. Seperti yang Anda lihat, fungsi-fungsi tersebut sebenarnya didefinisikan di tempat lain.
Pada contoh di atas, main () akan mencetak hello world hanya sekali, tetapi terus memasukkan bar_function (). Perhatikan juga, bar_function () tidak akan kembali dalam contoh ini (karena ini hanya contoh sederhana). Bayangkan saja stop_now sedang dimodifikasi ketika sinyal diservis (karenanya, volatile) jika ini tampaknya tidak cukup praktis.
Eksternal sangat berguna untuk hal-hal seperti penangan sinyal, mutex yang tidak ingin Anda taruh di header atau struktur, dll. Kebanyakan kompiler akan mengoptimalkan untuk memastikan bahwa mereka tidak menyimpan memori untuk objek eksternal, karena mereka tahu mereka akan menyimpannya dalam modul di mana objek didefinisikan. Namun, sekali lagi, ada gunanya menspesifikasikannya dengan kompiler modern saat membuat prototipe fungsi publik.
Semoga itu bisa membantu :)
sumber
bar.c
dan deklarasi difoo.c
. Jika fungsi dideklarasikan dalamfoo.h
dan kedua file termasukfoo.h
, maka header memberlakukan konsistensi antara kedua file sumber. Tanpa itu, jika definisibar_function
dalambar.c
perubahan tetapi deklarasi difoo.c
tidak diubah, maka ada yang salah pada saat run-time; kompiler tidak dapat menemukan masalah. Dengan header yang digunakan dengan benar, kompiler melihat masalah.Sejauh yang saya ingat standarnya, semua deklarasi fungsi dianggap sebagai "extern" secara default, jadi tidak perlu menentukannya secara eksplisit.
Itu tidak membuat kata kunci ini tidak berguna karena juga dapat digunakan dengan variabel (dan jika demikian - itu satu-satunya solusi untuk menyelesaikan masalah keterkaitan). Tetapi dengan fungsi - ya, itu opsional.
sumber
Anda perlu membedakan antara dua konsep terpisah: definisi fungsi dan pernyataan simbol. "extern" adalah pengubah tautan, petunjuk ke kompiler tentang di mana simbol yang dirujuk sesudahnya didefinisikan (petunjuknya adalah, "tidak di sini").
Jika saya menulis
dalam cakupan file (di luar blok fungsi) dalam file C, maka Anda mengatakan "variabel dapat didefinisikan di tempat lain".
adalah deklarasi fungsi f dan definisi fungsi f. Definisi dalam hal ini mengesampingkan eksternal.
pertama adalah deklarasi, diikuti oleh definisi.
Penggunaan
extern
salah jika Anda ingin mendeklarasikan dan sekaligus menentukan variabel cakupan file. Sebagai contoh,akan memberikan kesalahan atau peringatan, tergantung pada kompiler.
Penggunaan
extern
berguna jika Anda secara eksplisit ingin menghindari definisi variabel.Biarkan saya jelaskan:
Katakanlah file ac berisi:
File ah meliputi:
dan file bc berisi:
Extern di header berguna, karena memberitahu compiler selama fase tautan, "ini adalah deklarasi, dan bukan definisi". Jika saya menghapus baris dalam ac yang mendefinisikan i, mengalokasikan ruang untuknya dan memberikan nilai padanya, program harus gagal dikompilasi dengan referensi yang tidak ditentukan. Ini memberi tahu pengembang bahwa ia telah merujuk ke variabel, tetapi belum mendefinisikannya. Jika di sisi lain, saya menghilangkan kata kunci "extern", dan menghapus
int i = 2
baris, program masih mengkompilasi - saya akan didefinisikan dengan nilai default 0.Variabel ruang lingkup file secara implisit didefinisikan dengan nilai default 0 atau NULL jika Anda tidak secara eksplisit memberikan nilai padanya - tidak seperti variabel blok-lingkup yang Anda nyatakan di bagian atas fungsi. Kata kunci eksternal menghindari definisi tersirat ini, dan dengan demikian membantu menghindari kesalahan.
Untuk fungsi, dalam deklarasi fungsi, kata kunci memang berlebihan. Deklarasi fungsi tidak memiliki definisi implisit.
sumber
int i = 2
baris pada paragraf -3? Dan apakah benar untuk menyatakan, melihatint i;
, kompiler akan mengalokasikan memori untuk variabel itu, tetapi melihatextern int i;
, kompiler TIDAK akan mengalokasikan memori tetapi mencari variabel di tempat lain?Kata
extern
kunci mengambil bentuk yang berbeda tergantung pada lingkungan. Jika deklarasi tersedia,extern
kata kunci menggunakan tautan seperti yang ditentukan sebelumnya di unit terjemahan. Dengan tidak adanya deklarasi semacam itu,extern
tentukan hubungan eksternal.Berikut adalah paragraf yang relevan dari draft C99 (n1256):
sumber
Fungsi sebaris memiliki aturan khusus tentang apa
extern
artinya. (Perhatikan bahwa fungsi sebaris adalah ekstensi C99 atau GNU; mereka tidak dalam C. asliUntuk fungsi non-inline,
extern
tidak diperlukan karena diaktifkan secara default.Perhatikan bahwa aturan untuk C ++ berbeda. Misalnya,
extern "C"
diperlukan pada deklarasi C ++ fungsi C yang akan Anda panggil dari C ++, dan ada aturan yang berbeda tentanginline
.sumber
Itu sebabnya, 10 tahun kemudian:
extern
deklarasi fungsi untuk dihapus;git/git
mengikuti kesimpulan itu dan menghapusextern
dari kodenya (untuk Git 2.22, Q2 2019).Lihat komit ad6dad0 , komit b199d71 , komit 5545442 (29 Apr 2019) oleh Denton Liu (
Denton-L
) .(Digabung oleh Junio C Hamano -
gitster
- dalam komit 4aeeef3 , 13 Mei 2019)Ini tidak selalu mudah:
Lihat komit 7027f50 (04 Sep 2019) oleh Denton Liu (
Denton-L
) .(Digabung oleh Denton Liu -
Denton-L
- in commit 7027f50 , 05 Sep 2019)Perhatikan bahwa dengan Git 2.24 (Q4 2019), semua spurious
extern
dijatuhkan.Lihat komit 65904b8 (30 Sep 2019) oleh Emily Shaffer (
nasamuffin
) .Dibantu-oleh: Jeff King (
peff
) .Lihat komit 8464f94 (21 Sep 2019) oleh Denton Liu (
Denton-L
) .Dibantu-oleh: Jeff King (
peff
) .(Digabung oleh Junio C Hamano -
gitster
- dalam komit 59b19bc , 07 Okt 2019)sumber
Kata
extern
kunci memberi tahu kompiler bahwa fungsi atau variabel memiliki hubungan eksternal - dengan kata lain, itu terlihat dari file selain dari yang didefinisikan. Dalam pengertian ini memiliki arti yang berlawanan denganstatic
kata kunci. Agak aneh untuk diletakkanextern
pada saat definisi, karena tidak ada file lain yang memiliki visibilitas definisi (atau itu akan menghasilkan banyak definisi). Biasanya Anda meletakkanextern
deklarasi di beberapa titik dengan visibilitas eksternal (seperti file header) dan meletakkan definisi di tempat lain.sumber
mendeklarasikan fungsi extern berarti bahwa definisinya akan diselesaikan pada saat menghubungkan, bukan pada saat kompilasi.
Tidak seperti fungsi biasa, yang tidak dinyatakan sebagai eksternal, ia dapat didefinisikan di salah satu file sumber (tetapi tidak dalam beberapa file sumber jika tidak, Anda akan mendapatkan kesalahan linker yang mengatakan bahwa Anda telah memberikan banyak definisi fungsi) termasuk yang ada di yang dinyatakan extern. Jadi, dalam hal ini linker menyelesaikan definisi fungsi dalam file yang sama.
Saya tidak berpikir melakukan ini akan sangat berguna namun melakukan eksperimen semacam itu memberikan wawasan yang lebih baik tentang bagaimana kompiler dan penghubung bahasa bekerja.
sumber
Alasan tidak ada efeknya adalah karena pada saat tautan linker mencoba menyelesaikan definisi eksternal (dalam kasus Anda
extern int f()
). Tidak masalah jika ditemukan di file yang sama atau file yang berbeda, asalkan ditemukan.Semoga ini menjawab pertanyaan Anda.
sumber
extern
fungsi apa saja?