ฉันต้องการเข้าใจการเชื่อมโยงภายนอกและการเชื่อมโยงภายในและความแตกต่าง
ฉันยังต้องการทราบความหมายของ
const
การเชื่อมโยงตัวแปรภายในโดยค่าเริ่มต้นเว้นแต่จะประกาศเป็นextern
อย่างอื่น
ฉันต้องการเข้าใจการเชื่อมโยงภายนอกและการเชื่อมโยงภายในและความแตกต่าง
ฉันยังต้องการทราบความหมายของ
const
การเชื่อมโยงตัวแปรภายในโดยค่าเริ่มต้นเว้นแต่จะประกาศเป็นextern
อย่างอื่น
คำตอบ:
เมื่อคุณเขียนแฟ้มการดำเนินงาน ( .cpp
, .cxx
ฯลฯ ) คอมไพเลอร์ของคุณสร้างหน่วยการแปล นี่คือไฟล์ต้นฉบับจากการนำไปใช้ของคุณรวมถึงส่วนหัวทั้งหมดที่คุณ#include
มี
การเชื่อมโยงภายในหมายถึงทุกอย่างเพียง แต่อยู่ในขอบเขตของหน่วยการแปล
การเชื่อมโยงภายนอกหมายถึงสิ่งที่มีอยู่นอกเหนือหน่วยแปลเฉพาะ กล่าวอีกนัยหนึ่งสามารถเข้าถึงได้ผ่านโปรแกรมทั้งหมดซึ่งเป็นการรวมกันของหน่วยการแปลทั้งหมด (หรือไฟล์วัตถุ)
const
ตัวแปร (เช่นเดียวกับจุดประสงค์) ที่นี่พลาดโดยสิ้นเชิง
ดังที่dudewat กล่าวว่าการ เชื่อมโยงภายนอกหมายถึงสัญลักษณ์ (ฟังก์ชั่นหรือตัวแปรทั่วโลก) สามารถเข้าถึงได้ตลอดทั้งโปรแกรมของคุณและการเชื่อมโยงภายในหมายความว่าสามารถเข้าถึงได้ในหน่วยการแปลเดียวเท่านั้น
คุณสามารถควบคุมการเชื่อมโยงของสัญลักษณ์ได้อย่างชัดเจนโดยใช้extern
และstatic
คำหลัก หากไม่ได้ระบุการเชื่อมโยงการเชื่อมโยงเริ่มต้นจะใช้extern
สำหรับconst
สัญลักษณ์ที่ไม่ใช่และstatic
(ภายใน) สำหรับconst
สัญลักษณ์
// 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
โปรดทราบว่าแทนที่จะใช้static
สำหรับการเชื่อมโยงภายในจะเป็นการดีกว่าที่จะใช้เนมสเปซที่ไม่ระบุชื่อซึ่งคุณสามารถใส่class
es การเชื่อมโยงสำหรับเนมสเปซนิรนามมีการเปลี่ยนแปลงระหว่าง C ++ 98 และ C ++ 11 แต่สิ่งสำคัญคือพวกเขาไม่สามารถเข้าถึงได้จากหน่วยการแปลอื่น ๆ
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
ประกาศให้ตรงกันในไฟล์อื่นstatic
ประกาศด้วยคำหลัก ตัวแปรดังกล่าวจะกล่าวว่ามีการเชื่อมโยงภายในลองพิจารณาตัวอย่างต่อไปนี้:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
ประกาศf
ว่าเป็นฟังก์ชั่นที่มีการเชื่อมโยงภายนอก (เริ่มต้น) คำจำกัดความของคำนิยามจะต้องระบุไว้ในภายหลังในไฟล์นี้หรือในหน่วยการแปลอื่น (ที่ระบุด้านล่าง)max
ถูกกำหนดให้เป็นค่าคงที่จำนวนเต็ม เชื่อมโยงเริ่มต้นสำหรับค่าคงที่เป็นภายใน extern
การเชื่อมโยงของมันจะเปลี่ยนไปภายนอกที่มีคำหลัก ดังนั้นตอนนี้max
สามารถเข้าถึงได้ในไฟล์อื่นn
ถูกกำหนดให้เป็นตัวแปรจำนวนเต็ม เชื่อมโยงเริ่มต้นสำหรับตัวแปรที่กำหนดไว้นอกร่างกายของฟังก์ชั่นภายนอก#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;
}
max
มีการประกาศว่าจะมีการเชื่อมโยงภายนอก คำจำกัดความที่ตรงกันสำหรับmax
(พร้อมลิงก์ภายนอก) จะต้องปรากฏในไฟล์บางไฟล์ (เช่นเดียวกับใน 1.cpp)n
มีการประกาศว่าจะมีการเชื่อมโยงภายนอกz
ถูกกำหนดเป็นตัวแปรระดับโลกที่มีการเชื่อมโยงภายในnCall
ระบุว่าจะเป็นตัวแปรที่ยังคงความคุ้มค่าคุ้มข้ามสายไปยังฟังก์ชั่นnCall
f()
แตกต่างจากตัวแปรโลคัลที่มีคลาสหน่วยเก็บข้อมูลอัตโนมัติที่เป็นค่าเริ่มต้นnCall
จะถูกกำหนดค่าเริ่มต้นเพียงครั้งเดียวเมื่อเริ่มต้นโปรแกรมและไม่ใช่หนึ่งครั้งสำหรับการเรียกใช้แต่ละf()
ครั้ง ตัวระบุคลาสหน่วยเก็บข้อมูลstatic
มีผลกับอายุการใช้งานของตัวแปรโลคัลและไม่ใช่ขอบเขตหมายเหตุ:คำหลักstatic
มีบทบาทสองเท่า เมื่อนำมาใช้ในคำจำกัดความของตัวแปรโลกจะระบุการเชื่อมโยงภายใน เมื่อใช้ในคำจำกัดความของตัวแปรท้องถิ่นมันระบุว่าอายุการใช้งานของตัวแปรจะเป็นระยะเวลาของโปรแกรมแทนที่จะเป็นระยะเวลาของฟังก์ชัน
หวังว่าจะช่วย!
static
อนุญาตให้เริ่มต้นเดี่ยวขี้เกียจ (ซึ่งจะมีประโยชน์หากคุณต้องการวัตถุ Global-ish แต่ต้องควบคุมเมื่อมันถูกสร้างขึ้นเนื่องจากปัญหาเกี่ยวกับคำสั่งการก่อสร้างทั่วโลกและไม่สามารถจัดสรรแบบไดนามิกได้ ใช้new
ในขณะที่แผนการเริ่มต้นในเชิงลึกเพิ่มเติมอาจเกินสิ่งที่จำเป็นสำหรับวัตถุในคำถามโดยนัยนี่เป็นปัญหาหลักในระบบฝังตัวที่ใช้ C ++)
ให้พูดคุยเกี่ยวกับขอบเขตที่แตกต่างใน 'C'
ขอบเขต: โดยทั่วไปแล้วฉันจะเห็นอะไรและไกลเท่าไหร่
ตัวแปรท้องถิ่น: ขอบเขตอยู่ภายในฟังก์ชันเท่านั้น มันอยู่ในพื้นที่สแต็คของ RAM ซึ่งหมายความว่าทุกครั้งที่ฟังก์ชั่นได้รับการเรียกตัวแปรทั้งหมดที่เป็นส่วนหนึ่งของฟังก์ชั่นนั้นรวมถึงข้อโต้แย้งฟังก์ชั่นจะถูกสร้างขึ้นใหม่และจะถูกทำลายเมื่อการควบคุมออกไปจากฟังก์ชั่น (เพราะสแต็กจะถูกลบทิ้งทุกครั้งที่ฟังก์ชันส่งคืน)
ตัวแปรคงที่: ขอบเขตของสิ่งนี้สำหรับไฟล์ มันสามารถเข้าถึงได้ทุกที่ในไฟล์
ที่มีการประกาศ มันอยู่ในส่วน DATA ของ RAM ตั้งแต่นี้สามารถเข้าถึงได้ภายในไฟล์และด้วยเหตุนี้การเชื่อมโยงภายใน ใด ๆ
ไฟล์อื่น ๆ ไม่สามารถดูตัวแปรนี้ ในความเป็นจริงคำหลัก STATIC เป็นวิธีเดียวที่เราสามารถแนะนำระดับข้อมูลหรือฟังก์ชั่นบางอย่างที่
ซ่อนอยู่ใน 'C'
ตัวแปรทั่วโลก: ขอบเขตของสิ่งนี้สำหรับทั้งแอปพลิเคชัน มันเป็นรูปแบบที่สามารถเข้าถึงได้ทุกที่ของแอปพลิเคชัน ตัวแปรทั่วโลกยังอยู่ในส่วนข้อมูลเนื่องจากสามารถเข้าถึงได้ทุกที่ในแอปพลิเคชันและด้วยการเชื่อมโยงภายนอก
โดยค่าเริ่มต้นฟังก์ชั่นทั้งหมดอยู่ในระดับโลก ในกรณีที่คุณต้องการซ่อนบางฟังก์ชั่นในไฟล์จากภายนอกคุณสามารถใส่คีย์เวิร์ด static ให้กับฟังก์ชั่นนั้นได้ :-)
ก่อนที่จะพูดคุยเกี่ยวกับคำถามที่ว่ามันจะดีกว่าที่จะรู้ว่าคำแปลหน่วย , โปรแกรมและบางแนวคิดพื้นฐานของภาษา C ++ (อันที่จริงการเชื่อมโยงเป็นหนึ่งในพวกเขาในทั่วไป) ได้อย่างแม่นยำ นอกจากนี้คุณยังจะต้องรู้ว่าสิ่งที่เป็นขอบเขต
ฉันจะเน้นประเด็นสำคัญบางอย่างโดยเฉพาะ ที่หายไปในคำตอบก่อนหน้า
เชื่อมโยงเป็นทรัพย์สินของเป็นชื่อซึ่งเป็นที่รู้จักจากการประกาศ ชื่อที่ต่างกันสามารถแสดงถึงเอนทิตีเดียวกันได้(โดยทั่วไปคือวัตถุหรือฟังก์ชัน) ดังนั้นการพูดถึงการเชื่อมโยงของเอนทิตี้มักจะเป็นเรื่องไร้สาระเว้นแต่คุณจะแน่ใจว่าเอนทิตีจะถูกเรียกด้วยชื่อที่ไม่ซ้ำจากการประกาศเฉพาะบางอย่างเท่านั้น
หมายเหตุวัตถุเป็นเอนทิตี แต่ตัวแปรไม่ ขณะที่พูดถึงการเชื่อมโยงของตัวแปรจริงๆแล้วชื่อของเอนทิตีที่แสดงแทน (ซึ่งถูกนำเสนอโดยการประกาศเฉพาะ) นั้นเกี่ยวข้อง การเชื่อมโยงของชื่อเป็นหนึ่งในสาม: ไม่มีการเชื่อมโยงการเชื่อมโยงภายในหรือการเชื่อมโยงภายนอก
หน่วยการแปลที่แตกต่างกันสามารถแบ่งปันการประกาศเดียวกันโดยรวมไฟล์ส่วนหัว / ซอร์ส (ใช่เป็นถ้อยคำมาตรฐาน) ดังนั้นคุณอาจอ้างอิงชื่อเดียวกันในหน่วยการแปลที่แตกต่างกัน หากชื่อที่ประกาศมีการเชื่อมโยงภายนอกข้อมูลประจำตัวของเอนทิตีที่อ้างอิงชื่อจะถูกแชร์เช่นกัน หากชื่อที่ประกาศมีการเชื่อมโยงภายในชื่อเดียวกันในหน่วยการแปลที่แตกต่างกันแสดงถึงเอนทิตีที่แตกต่างกัน แต่คุณสามารถอ้างอิงเอนทิตีในขอบเขตที่แตกต่างกันของหน่วยการแปลเดียวกัน หากชื่อไม่มีการเชื่อมโยงคุณก็ไม่สามารถอ้างอิงเอนทิตีจากขอบเขตอื่น ๆ
(อุ๊ปส์ ... ฉันพบสิ่งที่ฉันพิมพ์แล้วค่อนข้างเพียงแค่ใช้ถ้อยคำมาตรฐานซ้ำ... )
นอกจากนี้ยังมีประเด็นที่สับสนอื่น ๆ ซึ่งไม่ได้ครอบคลุมอยู่ในข้อกำหนดภาษา
__attribute__
หรือ__declspec
) หรือตัวเลือกคอมไพเลอร์และภาพไม่ใช่โปรแกรมทั้งหมดหรือไฟล์อ็อบเจ็กต์ที่แปลจากหน่วยการแปลดังนั้นจึงไม่มีแนวคิดมาตรฐานที่สามารถอธิบายได้อย่างถูกต้อง เนื่องจากสัญลักษณ์ไม่ใช่คำศัพท์เชิงบรรทัดฐานใน C ++ จึงเป็นเพียงรายละเอียดการนำไปใช้งานแม้ว่าส่วนขยายของภาษาถิ่นที่เกี่ยวข้องอาจถูกนำมาใช้อย่างกว้างขวางกฎการเชื่อมโยงของขอบเขต namespace const
ตัวแปรเป็นสิ่งที่พิเศษ (และโดยเฉพาะอย่างยิ่งแตกต่างกันไปconst
วัตถุประกาศในขอบเขตแฟ้มในภาษา C ซึ่งยังมีแนวคิดของการเชื่อมโยงของตัวระบุ) ตั้งแต่ODRจะถูกบังคับใช้โดย C ++ มันเป็นสิ่งสำคัญที่จะให้ไม่เกินหนึ่งนิยามของตัวแปรเดียวกันหรือฟังก์ชั่นที่เกิดขึ้นในโปรแกรมทั้งหมดยกเว้นสำหรับinline
ฟังก์ชั่น หากไม่มีกฎพิเศษดังกล่าวconst
การประกาศconst
ตัวแปรที่ง่ายที่สุดด้วย initializers (เช่น= xxx
) ในส่วนหัวหรือไฟล์ต้นฉบับ (มักจะเป็น "ไฟล์ส่วนหัว") รวมอยู่ในหลายหน่วยการแปล (หรือรวมอยู่ในหนึ่งหน่วยการแปลมากกว่าหนึ่งครั้ง) แม้จะไม่ค่อยมี) ในโปรแกรมที่จะละเมิด ODR ซึ่งทำให้ใช้งานได้const
ไม่สามารถแทนที่มาโครที่มีลักษณะคล้ายวัตถุบางตัวได้
ฉันคิดว่าการเชื่อมโยงภายในและภายนอกใน C ++ให้คำอธิบายที่ชัดเจนและรัดกุม:
หน่วยการแปลหมายถึงไฟล์การนำไปใช้ (.c / .cpp) และไฟล์ส่วนหัว (.h / .hpp) ทั้งหมดที่มี หากวัตถุหรือฟังก์ชั่นภายในหน่วยการแปลนั้นมีการเชื่อมโยงภายในสัญลักษณ์ที่ระบุนั้นจะปรากฏแก่ผู้เชื่อมโยงภายในหน่วยการแปลนั้นเท่านั้น หากวัตถุหรือฟังก์ชั่นมีการเชื่อมโยงภายนอก linker สามารถมองเห็นได้เมื่อประมวลผลหน่วยการแปลอื่น ๆ คำสำคัญคงที่เมื่อใช้ใน namespace ส่วนกลางบังคับให้สัญลักษณ์มีการเชื่อมโยงภายใน คำหลักภายนอกจะส่งผลให้มีสัญลักษณ์ที่มีการเชื่อมโยงภายนอก
คอมไพเลอร์เริ่มต้นการเชื่อมโยงของสัญลักษณ์เช่นนั้น:
ตัวแปรโกลบอลที่ไม่ใช่ const มีการเชื่อมโยงภายนอกโดยค่าเริ่มต้น
ตัวแปรโกลบอล Const มีการเชื่อมโยงภายในโดยค่าเริ่มต้น
ฟังก์ชั่นมีการเชื่อมโยงภายนอกโดยค่าเริ่มต้น
การเชื่อมโยงกำหนดว่าตัวระบุที่มีชื่อเหมือนกันอ้างถึงวัตถุฟังก์ชันหรือเอนทิตีอื่น ๆ แม้ว่าตัวระบุเหล่านั้นจะปรากฏในหน่วยการแปลที่แตกต่างกันหรือไม่ การเชื่อมโยงของตัวระบุขึ้นอยู่กับวิธีการประกาศ การเชื่อมโยงมีสามประเภท:
c ++ เท่านั้น : คุณยังสามารถมีการเชื่อมโยงระหว่าง C ++ และไม่ใช่รหัส c ++ เศษซึ่งเรียกว่าการเชื่อมโยงภาษา
ที่มา: IBM Program Linkage
เป็นพื้น
extern linkage
ตัวแปรจะปรากฏในไฟล์ทั้งหมดinternal linkage
ตัวแปรจะปรากฏในไฟล์เดียวอธิบาย: ตัวแปร const เชื่อมโยงภายในโดยค่าเริ่มต้นเว้นแต่จะประกาศเป็นอย่างอื่นภายนอก
external linkage
const
ตัวแปรทั่วโลกคือinternal linkage
extern const
ตัวแปรพิเศษระดับโลกคือexternal linkage
วัสดุที่ดีเกี่ยวกับการเชื่อมโยงใน C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
ใน C ++
ตัวแปรใด ๆ ที่ขอบเขตไฟล์และที่ไม่ซ้อนอยู่ภายในคลาสหรือฟังก์ชันสามารถมองเห็นได้ตลอดหน่วยการแปลทั้งหมดในโปรแกรม สิ่งนี้เรียกว่าการเชื่อมโยงภายนอกเพราะในเวลาเชื่อมโยงชื่อจะปรากฏแก่ผู้เชื่อมโยงทุกที่ภายนอกหน่วยการแปลนั้น
ตัวแปรทั่วโลกและฟังก์ชั่นสามัญมีการเชื่อมโยงภายนอก
วัตถุคงที่หรือชื่อฟังก์ชั่นที่ขอบเขตไฟล์เป็นหน่วยการแปล ที่เรียกว่าเป็น Internal Linkage
การเชื่อมโยงหมายถึงองค์ประกอบที่มีที่อยู่ในลิงก์ / เวลาโหลดเท่านั้น ดังนั้นการประกาศคลาสและตัวแปรโลคัลไม่มีการเชื่อมโยง