Apa itu tautan eksternal dan tautan internal?

337

Saya ingin memahami hubungan eksternal dan hubungan internal serta perbedaannya.

Saya juga ingin tahu artinya

constvariabel secara internal terhubung secara default kecuali dinyatakan sebaliknya extern.

rkb
sumber

Jawaban:

279

Ketika Anda menulis sebuah file implementasi ( .cpp, .cxx, dll) compiler Anda menghasilkan unit terjemahan . Ini adalah file sumber dari implementasi Anda plus semua tajuk yang ada #includedi dalamnya.

Tautan internal mengacu pada segala sesuatu hanya dalam ruang lingkup unit terjemahan .

Tautan eksternal mengacu pada hal-hal yang ada di luar unit terjemahan tertentu. Dengan kata lain, dapat diakses melalui seluruh program , yang merupakan kombinasi dari semua unit terjemahan (atau file objek).

dudewat
sumber
112
Saya akan menghapus ini kecuali satu kesalahan: Unit terjemahan bukan "entah bagaimana file objek", itu kode sumber dari mana kompiler membuat file objek.
sbi
4
@ FrankHB, apa "sesuatu yang lebih penting" yang jawabannya hilang?
Ahli matematika
2
@Mathematician Maaf untuk terlambat ... Saya pikir masalahnya harus jelas (selain keakuratan kata-kata). Jawaban ini tidak lengkap, karena pertanyaan tentang aturan constvariabel (serta tujuannya) benar-benar hilang di sini.
FrankHB
294

Seperti kata dudewat tautan eksternal berarti simbol (fungsi atau variabel global) dapat diakses di seluruh program Anda dan tautan internal berarti bahwa itu hanya dapat diakses dalam satu unit terjemahan .

Anda dapat secara eksplisit mengontrol hubungan simbol dengan menggunakan kata kunci externdan static. Jika hubungan tidak ditentukan maka hubungan default adalah externuntuk non- constsimbol dan static(internal) untuk constsimbol.

// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static

// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static 

Perhatikan bahwa alih-alih menggunakan staticuntuk tautan internal, lebih baik menggunakan ruang nama anonim di mana Anda juga dapat menempatkan classes. Tautan untuk ruang nama anonim telah berubah antara C ++ 98 dan C ++ 11 tetapi yang utama adalah bahwa mereka tidak dapat dijangkau dari unit terjemahan lainnya.

namespace {
   int i; // external linkage but unreachable from other translation units.
   class invisible_to_others { };
}
Motti
sumber
11
Implementasi kata kunci "ekspor" menyoroti perbedaan antara fungsi yang dideklarasikan 'statis' dan fungsi yang dideklarasikan di namespace yang tidak disebutkan namanya. Untuk meringkas sebaik mungkin, templat fungsi yang dideklarasikan dengan kata kunci ekspor dalam satu unit terjemahan dapat merujuk ke fungsi yang didefinisikan dalam ruang nama yang tidak disebutkan namanya dari unit terjemahan yang berbeda sebagai hasil dari pencarian 2 fase. ( ddj.com/showArticle.jhtml?articleID=184401584 )
Richard Corden
Bagaimana jika saya melakukan hal berikut: 1.cpp <code> const int ci; </code> 2.cpp <code> extern const int ci; </code>
Rajendra Uppal
2
@Rajenda Anda akan mendapatkan kesalahan simbol yang belum terselesaikan (maaf atas keterlambatan sembilan bulan dalam menjawab saya melewatkan komentar ini).
Motti
4
Info yang mungkin sangat meningkatkan jawaban ini: 1) statis tidak ditinggalkan lagi di C ++ 11. 2) anggota namespace anonim di C ++ 11 memiliki hubungan internal secara default. Lihat stackoverflow.com/questions/10832940/...
Klaim
2
Apa artinya "hubungan eksternal tetapi tidak terjangkau dari unit terjemahan lain"? Bagaimana bisa tidak terjangkau tetapi masih eksternal?
szx
101
  • Variabel global secara default memiliki tautan eksternal . Cakupannya dapat diperluas ke file selain dari memuatnya dengan memberikan externdeklarasi yang cocok di file lain.
  • Cakupan variabel global dapat dibatasi pada file yang berisi deklarasi dengan mengawali deklarasi dengan kata kunci static. Variabel tersebut dikatakan memiliki hubungan internal .

Pertimbangkan contoh berikut:

1.cpp

void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
    int a;
    //...
    f(a);
    //...
    f(a);
    //...
}
  1. Tanda tangan fungsi fmenyatakan fsebagai fungsi dengan tautan eksternal (default). Definisinya harus diberikan nanti di file ini atau di unit terjemahan lain (diberikan di bawah).
  2. maxdidefinisikan sebagai konstanta integer. Tautan default untuk konstanta adalah internal . Keterkaitannya diubah menjadi eksternal dengan kata kunci extern. Jadi sekarang maxbisa diakses di file lain.
  3. ndidefinisikan sebagai variabel integer. Hubungan default untuk variabel yang ditentukan di luar badan fungsi adalah eksternal .

2.cpp

#include <iostream>
using namespace std;

extern const int max;
extern int n;
static float z = 0.0;

void f(int i)
{
    static int nCall = 0;
    int a;
    //...
    nCall++;
    n++;
    //...
    a = max * z;
    //...
    cout << "f() called " << nCall << " times." << endl;
}
  1. maxdinyatakan memiliki hubungan eksternal . Definisi yang cocok untuk max(dengan tautan eksternal) harus muncul di beberapa file. (Seperti pada 1.cpp)
  2. ndinyatakan memiliki hubungan eksternal .
  3. zadalah didefinisikan sebagai variabel global dengan hubungan internal .
  4. Definisi nCallmenentukan nCallmenjadi variabel yang mempertahankan nilainya melintasi panggilan ke fungsi f(). Tidak seperti variabel lokal dengan kelas penyimpanan otomatis default, nCallakan diinisialisasi hanya sekali pada awal program dan tidak sekali untuk setiap doa f(). Penentu kelas penyimpanan staticmemengaruhi masa pakai variabel lokal dan bukan cakupannya.

NB: Kata kunci staticmemainkan peran ganda. Ketika digunakan dalam definisi variabel global, ini menentukan hubungan internal . Ketika digunakan dalam definisi variabel lokal, itu menentukan bahwa masa pakai variabel akan menjadi durasi program bukannya durasi fungsi.

Semoga itu bisa membantu!

Rajendra Uppal
sumber
2
Yang penting, ketika digunakan dalam definisi variabel lokal, staticmemungkinkan inisialisasi tunggal malas (yang dapat berguna jika Anda memerlukan objek global-ish tetapi harus mengontrol ketika itu dibangun karena masalah dengan urutan konstruksi global dan tidak dapat secara dinamis mengalokasikannya menggunakan newsementara skema inisialisasi yang lebih mendalam mungkin melampaui apa yang diperlukan untuk objek yang bersangkutan; dengan implikasi, ini terutama merupakan masalah pada sistem embedded yang menggunakan C ++).
JAB
1
Sangat Bagus, Buatlah hari saya.
Blood-HaZaRd
28

Dalam hal 'C' (Karena kata kunci statis memiliki arti yang berbeda antara 'C' & 'C ++')

Mari kita bicara tentang ruang lingkup yang berbeda di 'C'

RUANG LINGKUP: Pada dasarnya berapa lama saya bisa melihat sesuatu dan seberapa jauh.

  1. Variabel lokal: Lingkup hanya di dalam fungsi. Itu berada di area STACK RAM. Yang berarti bahwa setiap kali suatu fungsi dipanggil semua variabel yang merupakan bagian dari fungsi itu, termasuk argumen fungsi yang baru dibuat dan dihancurkan setelah kontrol keluar dari fungsi. (Karena tumpukan memerah setiap fungsi kembali)

  2. Variabel statis: Cakupan ini untuk file. Ini dapat diakses di mana saja di file
    yang dideklarasikan. Itu berada di segmen DATA RAM. Karena ini hanya dapat diakses di dalam file dan karenanya tautan INTERNAL. Setiap
    file lainnya tidak bisa melihat variabel ini. Sebenarnya kata kunci STATIC adalah satu-satunya cara di mana kita dapat memperkenalkan beberapa level data atau fungsi
    bersembunyi di 'C'

  3. Variabel global: Cakupan ini untuk seluruh aplikasi. Ini dapat diakses dari setiap tempat aplikasi. Variabel global juga berada di segmen DATA Karena dapat diakses di mana saja dalam aplikasi dan karenanya EKSTERNAL Linkage

Secara default semua fungsi bersifat global. Jika Anda perlu menyembunyikan beberapa fungsi dalam file dari luar, Anda dapat awalan kata kunci statis ke fungsi. :-)

Libin Jose
sumber
12
@ Libin: Adapun 1) variabel lokal tidak harus di stack - mereka biasanya di stack tetapi bisa di register dan di lingkungan ARM mereka lebih sering di register daripada di stack (tergantung pada beberapa faktor - level panggilan, nomor argumen resmi ..)
Artur
4
@ Libin: Adapun 1) Jika Anda menganggap 'flush' sebagai ditimpa - ini salah. Stack pointer baru saja dipindahkan ke tempat yang berbeda. Tidak ada 'vars lokal yang sebelumnya valid' adalah 'flushed' / dibersihkan dll. Anda mencampur ruang lingkup variabel dengan durasi penyimpanan. Lingkup memberitahu dari mana Anda dapat mengakses var. Durasi penyimpanan menunjukkan berapa lama itu ada. Anda dapat memiliki variabel lokal dengan durasi penyimpanan statis. Ini berarti ia hidup "selamanya" tetapi dapat diakses dari fungsi yang dideklarasikan.
Artur
2
Downvote untuk konsep yang tidak akurat dan kesalahpahaman yang jelas. Sebenarnya, tidak ada "global" atau "variabel" (sebagai kata benda) yang didefinisikan dalam C. Anda mungkin ingin merujuk "file scope object" daripada "variabel global", tetapi berbicara tentang "scope" (dalam bahasa C adalah properti pengidentifikasi ) itu tidak masuk akal. (Kedua istilah tersebut didefinisikan dalam C ++ secara normatif dengan makna yang sedikit berbeda.)
FrankHB
@ Artur saya pikir Anda lupa " hanya " di " Ini berarti ia hidup" selamanya "tetapi dapat diakses (hanya) dari fungsi yang dideklarasikan. " - Ini adalah detail penting, maka saya ingin menunjukkan itu secara eksplisit.
RobertS mendukung Monica Cellio
14

Sebelum berbicara tentang pertanyaan, lebih baik untuk mengetahui istilah unit terjemahan , program dan beberapa konsep dasar C ++ (sebenarnya keterkaitan adalah salah satunya secara umum) tepatnya. Anda juga harus tahu apa itu ruang lingkup .

Saya akan menekankan beberapa poin penting, khususnya. yang hilang dalam jawaban sebelumnya.

Linkage adalah properti dari nama , yang diperkenalkan oleh deklarasi . Nama yang berbeda dapat menunjukkan entitas yang sama (biasanya, objek atau fungsi). Jadi, berbicara tentang hubungan suatu entitas biasanya tidak masuk akal, kecuali jika Anda yakin bahwa entitas tersebut hanya akan dirujuk dengan nama unik dari beberapa deklarasi tertentu (biasanya satu deklarasi).

Catatan objek adalah entitas, tetapi variabel tidak. Saat berbicara tentang keterkaitan variabel, sebenarnya nama entitas yang ditandai (yang diperkenalkan oleh deklarasi tertentu) terkait. Tautan nama dalam salah satu dari tiga: tidak ada hubungan, hubungan internal atau hubungan eksternal.

Unit terjemahan yang berbeda dapat membagikan deklarasi yang sama dengan file header / sumber (ya, itu adalah kata-kata standar) yang disertakan. Jadi, Anda dapat merujuk nama yang sama di unit terjemahan yang berbeda. Jika nama yang dideklarasikan memiliki tautan eksternal, identitas entitas yang dirujuk oleh nama tersebut juga dibagikan. Jika nama yang dideklarasikan memiliki hubungan internal, nama yang sama di unit terjemahan yang berbeda menunjukkan entitas yang berbeda, tetapi Anda dapat merujuk entitas dalam lingkup yang berbeda dari unit terjemahan yang sama. Jika nama tidak memiliki tautan, Anda tidak dapat merujuk entitas dari lingkup lain.

(Ups ... Saya menemukan apa yang saya ketik agak hanya mengulangi kata-kata standar ...)

Ada juga beberapa poin membingungkan lainnya yang tidak tercakup oleh spesifikasi bahasa.

  1. Visibilitas (nama). Ini juga merupakan properti dari nama yang dideklarasikan, tetapi dengan makna yang berbeda dengan tautan .
  2. Visibilitas (efek samping) . Ini tidak terkait dengan topik ini.
  3. Visibilitas (simbol). Gagasan ini dapat digunakan oleh implementasi aktual . Dalam implementasi seperti itu, simbol dengan visibilitas khusus dalam kode objek (biner) biasanya target dipetakan dari definisi entitas yang namanya memiliki hubungan spesifik yang sama dalam kode sumber (C ++). Namun, biasanya tidak dijamin satu-ke-satu. Misalnya, simbol dalam gambar pustaka dinamis dapat ditentukan hanya dibagikan dalam gambar itu secara internal dari kode sumber (terlibat dengan beberapa ekstensi, biasanya,__attribute__ atau__declspec) atau opsi penyusun, dan gambar bukanlah keseluruhan program atau file objek yang diterjemahkan dari unit terjemahan, sehingga tidak ada konsep standar yang dapat menggambarkannya secara akurat. Karena simbol bukan istilah normatif dalam C ++, itu hanya detail implementasi, meskipun ekstensi dialek terkait mungkin telah diadopsi secara luas.
  4. Aksesibilitas. Dalam C ++, ini biasanya tentang properti anggota kelas atau kelas dasar , yang lagi-lagi konsep berbeda yang tidak terkait dengan topik.
  5. Global. Dalam C ++, "global" merujuk pada sesuatu namespace global atau lingkup namespace global. Yang terakhir kira-kira setara dengan ruang lingkup file dalam bahasa C. Baik di C dan C ++, hubungan tidak ada hubungannya dengan ruang lingkup, meskipun ruang lingkup (seperti tautan) juga sangat terkait dengan pengidentifikasi (dalam C) atau nama (dalam C ++) yang diperkenalkan oleh beberapa deklarasi.

The Aturan linkage lingkup namespace constvariabel adalah sesuatu yang istimewa (dan terutama yang berbeda dengan constobjek dideklarasikan di lingkup berkas dalam bahasa C yang juga memiliki konsep linkage pengidentifikasi). Karena ODR diberlakukan oleh C ++, penting untuk menjaga tidak lebih dari satu definisi variabel atau fungsi yang sama terjadi di seluruh program kecuali untuk inlinefungsi . Jika tidak ada aturan khusus const, deklarasi constvariabel paling sederhana dengan inisialisasi (mis.= xxx ) dalam header atau file sumber (sering kali "file header") dimasukkan oleh beberapa unit terjemahan (atau disertakan oleh satu unit terjemahan lebih dari satu kali, meskipun jarang) dalam suatu program akan melanggar ODR, yang membuatnya digunakanconst variabel sebagai penggantian beberapa makro objek-seperti tidak mungkin.

FrankHB
sumber
3
Jawaban ini terdengar sangat mahir dan mungkin sangat tepat (saya tidak bisa menilai itu) tetapi kemungkinan besar itu tidak dapat dimengerti seperti yang diinginkan oleh banyak orang yang mencari pertanyaan ini di sini daripada langsung membaca spesifikasi bahasa. Setidaknya untuk kebutuhan saya, saya akan tetap dengan jawaban yang diterima tetapi masih berterima kasih karena telah memberikan wawasan kecil tentang spesifikasi bahasa. 👍🏻
wedi
8

Saya pikir Hubungan Internal dan Eksternal di C ++ memberikan penjelasan yang jelas dan ringkas:

Unit terjemahan mengacu pada file implementasi (.c / .cpp) dan semua file header (.h / .hpp) yang disertakan. Jika suatu objek atau fungsi di dalam unit terjemahan tersebut memiliki hubungan internal, maka simbol spesifik tersebut hanya dapat dilihat oleh linker di dalam unit terjemahan itu. Jika suatu objek atau fungsi memiliki tautan eksternal, tautan tersebut juga dapat melihatnya saat memproses unit terjemahan lainnya. Kata kunci statis, ketika digunakan dalam namespace global, memaksa simbol untuk memiliki tautan internal. Kata kunci eksternal menghasilkan simbol yang memiliki tautan eksternal.

Kompiler secara default menautkan simbol sehingga:

Variabel global non-const memiliki hubungan eksternal secara default
variabel global Const memiliki hubungan internal secara default
Fungsi memiliki hubungan eksternal secara default

Nan Xiao
sumber
6

Linkage menentukan apakah pengidentifikasi yang memiliki nama identik merujuk pada objek, fungsi, atau entitas lain yang sama, bahkan jika pengidentifikasi tersebut muncul di unit terjemahan yang berbeda. Tautan pengenal tergantung pada bagaimana hal itu dinyatakan. Ada tiga jenis hubungan:

  1. Tautan internal : pengidentifikasi hanya dapat dilihat dalam unit terjemahan.
  2. Tautan eksternal : pengidentifikasi dapat dilihat (dan dirujuk) di unit terjemahan lainnya.
  3. Tanpa tautan : pengidentifikasi hanya dapat dilihat dalam cakupan definisi mereka. Tautan tidak memengaruhi pelingkupan

Khusus C ++ : Anda juga dapat memiliki keterkaitan antara fragmen kode C ++ dan non-C ++, yang disebut bahasa linkage .

Sumber: Tautan Program IBM

arun sobat
sumber
5

Pada dasarnya

  • extern linkage variabel terlihat di semua file
  • internal linkage variabel terlihat dalam satu file.

Jelaskan: variabel const tautan internal secara default kecuali dinyatakan sebaliknya sebagai eksternal

  1. secara default, variabel global adalah external linkage
  2. tetapi, constvariabel global adalahinternal linkage
  3. ekstra, extern constvariabel global adalahexternal linkage

Materi yang cukup bagus tentang tautan di C ++

http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/

Warna
sumber
1

Dalam C ++

Setiap variabel pada lingkup file dan yang tidak bersarang di dalam kelas atau fungsi, terlihat di seluruh unit terjemahan dalam suatu program. Ini disebut tautan eksternal karena pada waktu tautan nama tersebut dapat dilihat oleh tautan di mana saja, di luar unit terjemahan itu.

Variabel global dan fungsi biasa memiliki hubungan eksternal.

Objek statis atau nama fungsi pada lingkup file bersifat lokal ke unit terjemahan. Itulah yang disebut dengan Internal Linkage

Linkage hanya merujuk ke elemen yang memiliki alamat pada tautan / waktu buka; dengan demikian, deklarasi kelas dan variabel lokal tidak memiliki keterkaitan.

Saurabh Raoot
sumber
vars global const memiliki hubungan internal.
Blood-HaZaRd