C++ 內(nèi)部鏈接 vs 外部鏈接

ref: https://www.geeksforgeeks.org/internal-linkage-external-linkage-c/

導(dǎo)讀

生命周期(scope)和鏈接方式(linkage)很容易混淆,本文主要介紹生命周期和鏈接方式在C++中如何起作用的。

定義

  • 生命周期(scope): 生命周期是指一個標識符(變量、常亮、類、對象、方法)可以訪問的范圍。

  • 鏈接方式(linkage):鏈接描述標識符如何在整個程序或單個翻譯單元中引用相同的實體。
    Internal Linkage and External Linkage

  • 翻譯單元(Translation Unit ): 翻譯單元是包含源代碼、頭文件和其他依賴項的文件。所有這些源都被組合在一個文件中,用來產(chǎn)生一個單獨的可執(zhí)行對象。以有意義的方式將這些資源鏈接在一起是很重要的。例如,編譯器應(yīng)該知道printf定義位于stdio頭文件中。

  • 說明:生命周期在編譯期間起作用,鏈接方式在鏈接期間起作用。scope is a property handled by compiler, whereas linkage is a property handled by linker.

  • 內(nèi)部鏈接(Internal Linkage): 一個標識符僅在當前翻譯單元使用,通常可以使用關(guān)鍵字static標識為內(nèi)部鏈接。

  • 外部鏈接(External Linkage): 一個標識符在所有的翻譯單元中可以使用,即在所有翻譯單元共享,通??梢允褂藐P(guān)鍵字extern標識為外部鏈接。

舉例

內(nèi)部鏈接

代碼

// Animal.h
#ifndef ANIMAL_H_
#define ANIMAL_H_

void call_me(void);

static int animals = 8;
const int i = 5;

#endif
//Animal.cpp

#include <stdio.h>
#include "Animal.h"
void call_me(void)
{
    printf("const int i=%d, static int animals = %d\n", i, animals);
    printf("in Animal.cpp &i = %p,&animals = %p\n", &i, &animals);
}
// Feed.cpp
#include <stdio.h>
#include "Animal.h"
  
int main()
{
    printf("before change aninals:");
    call_me();
    animals = 2;
    printf("after change aninals:");
    printf("animals = %d\n", animals);
    call_me();

    printf("in Feed.cpp &i = %p,&animals = %p\n", &i, &animals);
    return 0;
}

編譯鏈接

% g++ Feed.cpp Animal.cpp -o Feed  

運行

% ./Feed
before change aninals:const int i=5, static int animals = 8
in Animal.cpp &i = 0x10081dfa8,&animals = 0x100822014
after change aninals:animals = 2
const int i=5, static int animals = 8
in Animal.cpp &i = 0x10081dfa8,&animals = 0x100822014
in Feed.cpp &i = 0x10081dfa4,&animals = 0x100822010

分析

在Animal.cpp和Feed.cpp中, 變量i和animals的地址是不同的,即每個文件都是不同的變量。

外部鏈接

代碼

// Animal.h
#ifndef ANIMAL_H_
#define ANIMAL_H_

void call_me(void);
extern int animals ;
extern const int i;

#endif
// Animal.cpp
#include <stdio.h>
#include "Animal.h"
int animals = 8;
const int i = 5;
void call_me(void)
{
    printf("const int i=%d, static int animals = %d\n", i, animals);
    printf("in Animal.cpp &i = %p,&animals = %p\n", &i, &animals);
}
// Feed.cpp
#include <stdio.h>
#include "Animal.h"
  
int main()
{
    printf("before change aninals:");
    call_me();
    animals = 2;
    printf("after change aninals:");
    printf("animals = %d\n", animals);
    call_me();

    printf("in Feed.cpp &i = %p,&animals = %p\n", &i, &animals);
    return 0;
}

編譯鏈接

% g++ Feed.cpp Animal.cpp -o Feed  

運行

% ./Feed
before change aninals:const int i=5, static int animals = 8
in Animal.cpp &i = 0x100d14fb4,&animals = 0x100d19010
after change aninals:animals = 2
const int i=5, static int animals = 2
in Animal.cpp &i = 0x100d14fb4,&animals = 0x100d19010
in Feed.cpp &i = 0x100d14fb4,&animals = 0x100d19010

分析

在Animal.cpp和Feed.cpp中, 變量i和animals的地址是相同的,即所有的文件中該變量是共享的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 原理 1.1 首先,關(guān)于聲明和定義的區(qū)別。 這種寫法(函數(shù)原型后加;號表示結(jié)束的寫法)只能叫函數(shù)聲明而不能叫函...
    Pitfalls閱讀 6,820評論 2 12
  • 在運行 c++ 代碼前,編譯器和連接器的需要完成它們的工作。至于編譯器和連接器是如何運作,本文就不作敘述。如果想要...
    Babyccino閱讀 637評論 0 0
  • 前言 編譯的主要任務(wù)是將源代碼文件作為輸入,最終輸出目標文件,這期間發(fā)生了什么?便是我們本篇文章要介紹的。在開始之...
    QiShare閱讀 4,698評論 0 7
  • 前言 編譯的主要任務(wù)是將源代碼文件作為輸入,最終輸出目標文件,這期間發(fā)生了什么?便是我們本篇文章要介紹的。在開始之...
    沐靈洛閱讀 3,402評論 0 2
  • 相關(guān)概念: 1.自動存儲持續(xù)性:聲明的變量的存儲持續(xù)性是自動的,在開始執(zhí)行其函數(shù)或代碼塊時被創(chuàng)建,執(zhí)行完畢后他們使...
    禿頭俠JeFF閱讀 493評論 0 2

友情鏈接更多精彩內(nèi)容