亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

淺談C語言中的強符號、弱符號、強引用和弱引用

2020-01-26 15:11:45
字體:
來源:轉載
供稿:網友

首先我表示很悲劇,在看《程序員的自我修養--鏈接、裝載與庫》之前我竟不知道C有強符號、弱符號、強引用和弱引用。在看到3.5.5節弱符號和強符號時,我感覺有些困惑,所以寫下此篇,希望能和同樣感覺的朋友交流也希望高人指點。

  首先我們看一下書中關于它們的定義。

  引入場景:(1)文件A中定義并初始化變量i(int i = 1), 文件B中定義并初始化變量i(int i = 2)。編譯鏈接A、B時會報錯b.o:(.data+0x0): multiple definition of `i';a.o:(.data+0x0): multiple definition of `i'。(2)在文件C中定義并初始化兩個變量i(int i = 1; int i = 2), 編譯鏈接時會報錯c.c:2:5: error: redefinition of ‘i'; c.c:1:5: note: previous definition of ‘i' was here。

  強符號:像場景中這樣的符號定義被稱為強符號,對于C/C++來說,編譯器默認函數和初始化的全局變量為強符號。
  弱符號:接上文,為初始化的全局變量為弱符號。
  編譯器關于強弱符號的規則有:(1)強符號不允許多次定義,但強弱可以共存;(2)強弱共存時,強覆蓋弱;(3)都是弱符號時,選擇占用空間最大的,如選擇  double類型的而不選擇int類型的。

  由以上定義所以有我之前沒有想到的場景:
  代碼a.c:

1 int i = 2;
  代碼b.c:

復制代碼 代碼如下:

#include<stdio.h>

int i;
int main(int argc, char** argv)
{
      printf("i = %d/n", i);
      return 0;     
}

  編譯文件a和b并鏈接,結果輸出i為2而不是0。
  并且在同一個文件中定義但未初始化兩個相同的變量不會報錯,只有在使用變量時才會報錯。
  對于GCC編譯器來說,還允許使用__attribute__((weak))來將強符號定義為弱符號,所已有
  代碼c.c

復制代碼 代碼如下:

 #include<stdio.h>
 
  __attribute__((weak)) int i = 1;
 
  int main(int argc, char** argv)
  {
       printf("i = %d/n", i);
       return 0;  
  }

  結果i的輸出仍未2而不是1。

  那么對于函數而言是不是也這樣呢?先不看函數,而是先看由強弱符號而進一步引入的強弱引用。書中關于強弱引用的概述是對于強引用若未定義則鏈接時肯定會報錯,而對于弱引用則不會報錯,鏈接器默認其為0(這一點對于函數好理解,即函數符號所代表入口地址為0;對于變量就要注意了,既然是引用那自然就是地址了,所以同函數一樣變量的地址為0而不是變量的值為0)。此時對于強弱引用是不是還沒有什么明確的概念呢?到底什么是引用?引用和符號又是什么關系?這里我說一下我的理解(歡迎指正),在定義和聲明處指定的函數名、變量名即為對應的符號,而在代碼其他處調用函數或使用變量時,則把函說明和變量名看作引用,這樣一來符號和引用在代碼層面上其實就是一個東西,只是根據環境而叫法不同而已。那么強符號對應強引用,弱符號對應弱引用。

  有上面的強弱引用的特點可看出,當一個函數為弱引用時,不管這個函數有沒有定義,鏈接時都不會報錯,而且我們可以根據判斷函數名是否為0來決定是否執行這個函數。這樣一來,包含這些函數的庫就可以以模塊、插件的形式和我們的引用組合一起,方便使用和卸載,并且由于強符號可以覆蓋弱符號和強弱符號與強弱引用的關系可知,我們自己定義函數可以覆蓋庫中的函數,多么美妙。

  先看根據條件判斷是否執行函數:
  代碼d.c

復制代碼 代碼如下:

 #include<stdio.h>
 
void func()
{
     printf("func()#1/n");
}

  代碼e.c

復制代碼 代碼如下:

 #include<stdio.h>
 
 __attribute__((weak)) void func();
 
 int main(int argc, char** argv)
 {
      if (func)
          func();
      return 0;
 }

  編譯d.c,cc -c d.c 輸出d.o;編譯e.c并鏈接d.o,cc d.o e.c -o e輸出可執行文件e,運行e正常執行函數func。編譯e.c但不鏈接d.o,此時并不會報錯,只不過func不會執行,因為沒有它的定義所以if(func)為假。
  再看函數覆蓋:
  代碼f.c

復制代碼 代碼如下:

 #include<stdio.h>
 
 __attribute__((weak)) void func()
 {
      printf("func()#1/n");
 }

  代碼g.c

復制代碼 代碼如下:

 #include<stdio.h>
 
 void func()
 {
      printf("func()#2/n");
  }
 
 int main(int argc, char** argv)
 {
      func();
      return 0;
 }
 ~      

  編譯鏈接,結構輸出"func()#2"。

  以上可以說明函數和變量是保持一致的,其實對應變量也可以像使用函數那樣先判斷再使用,只不過不是判斷變量的值而是變量的地址,如
  代碼v1.c

復制代碼 代碼如下:

int i = 2;

  代碼v2.c

復制代碼 代碼如下:

 #include<stdio.h>
 
 __attribute__((weak)) extern int i;
 
 int main(int argc, char** argv)
 {
      if (&i)
          printf("i = %d/n", i);
     return 0;
 }
 ~      

  編譯并鏈接v1時,輸出2;編譯但不鏈接v1時無輸出。這樣做時要分清定義和聲明的區別,__attribute__((weak)) int i 是定義變量并轉換為弱符號,這樣i是分配了空間的,而__attribute__((weak)) extern int i 則將原來定義的變量i由強符號轉換為弱符號,導致使用i時不是強引用而是弱引用。不過雖然變量可以這么做但沒有函數那樣有意義。

  上面關于強弱引用仍舊使用的是GCC提供的__attribute__((weak)),而書中還提到了__attribute__((weakref)),后者貌似更能體現“引用”這一關鍵詞。而我之所以使用前者來介紹強弱引用,是因為我對關于強弱符號與強弱引用對應關系的理解。關于__attribute__((weakref))的使用方法,這里介紹一種(兩者都有不同的使用方法)。
  代碼a.c

復制代碼 代碼如下:

 #include<stdio.h>
 
 void bar()
 {
      printf("foo()/n");
 }

  代碼b.c

復制代碼 代碼如下:

 #include<stdio.h>
 
 static void foo() __attribute__((weakref("bar")));
 
  int main(int argc, char** argv)
 {
      if (foo)
         foo();
 
      return 0;
 }

  注意函數foo的static修飾符,沒有的話會報錯,這樣將函數foo限制在只有本文件內可使用。

  好了,夜已深,寫的有點凌亂,我也凌亂了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩资源在线观看| 亚洲午夜激情免费视频| 成人福利免费观看| 亚洲第一网站免费视频| 夜夜嗨av一区二区三区免费区| 国产精品九九久久久久久久| 亚洲人成免费电影| 日本在线观看天堂男亚洲| 国产综合色香蕉精品| 久久久久国产一区二区三区| 成人h片在线播放免费网站| 成人h视频在线观看播放| 久久999免费视频| 性欧美激情精品| 国产精品美乳一区二区免费| 国产日韩欧美自拍| 国产精品丝袜一区二区三区| 亚洲综合日韩在线| 91豆花精品一区| 国产欧美va欧美va香蕉在| 疯狂欧美牲乱大交777| 爱福利视频一区| 国产美女主播一区| 久久久www成人免费精品| 国产日韩精品在线观看| 久久久亚洲国产| 国产成人精品久久久| 欧美日韩国产精品专区| 欧美性高潮床叫视频| 国产精品久久视频| 久久九九精品99国产精品| 中文字幕亚洲欧美| 欧美国产高跟鞋裸体秀xxxhd| 国产精品中文字幕久久久| 亚洲图片在线综合| 日韩小视频在线| 日韩在线欧美在线| 欧美日韩中文字幕在线视频| wwwwwwww亚洲| 国产在线观看一区二区三区| 欧美一级片久久久久久久| 国产亚洲日本欧美韩国| 亚洲最大av在线| 国内精品久久久久久| 色多多国产成人永久免费网站| 欧美激情网站在线观看| 91高清视频免费观看| 国产精品久久久久久搜索| 精品无人区太爽高潮在线播放| 国产精品免费视频xxxx| 69影院欧美专区视频| 精品女同一区二区三区在线播放| 国产欧美亚洲视频| 精品一区二区三区电影| 欧美午夜视频在线观看| 18久久久久久| 国产精品福利小视频| 国产精品吴梦梦| 亚洲激情在线观看| 国产一区红桃视频| 久久久亚洲精品视频| 日本乱人伦a精品| 欧美激情精品久久久久久大尺度| 在线免费观看羞羞视频一区二区| 国产一区二区欧美日韩| 91国内免费在线视频| 日韩中文在线视频| 萌白酱国产一区二区| 亚洲精品久久久久| 91精品国产成人| 久久99久久99精品免观看粉嫩| 午夜精品理论片| 欧美激情一区二区三区在线视频观看| 欧美中文字幕在线| 欧美大肥婆大肥bbbbb| 日韩在线观看免费高清完整版| 久久久国产精品亚洲一区| 欧美性高跟鞋xxxxhd| 久久精品99国产精品酒店日本| 国产精品亚洲视频在线观看| 欧美精品激情blacked18| 在线成人激情视频| 久久精品国产v日韩v亚洲| 精品国产成人av| 欧美另类99xxxxx| 欧美精品久久久久久久| 久久精品国产成人| 久热在线中文字幕色999舞| 久久免费视频在线| 国产精品直播网红| 国产精品高潮呻吟久久av野狼| 色中色综合影院手机版在线观看| 日韩欧美成人免费视频| 国产亚洲精品一区二区| 欧美日韩视频免费播放| 中文字幕亚洲国产| 成人乱色短篇合集| 91久久国产综合久久91精品网站| 在线日韩中文字幕| 精品偷拍一区二区三区在线看| 久久成人综合视频| 91精品视频网站| 欧美激情xxxx性bbbb| 26uuu亚洲伊人春色| 亚洲国产婷婷香蕉久久久久久| 久久精品中文字幕电影| 亚洲a一级视频| 亚洲福利在线观看| 久久夜色精品亚洲噜噜国产mv| 久久久久这里只有精品| 日韩av在线网址| 日韩专区在线播放| 久久中文精品视频| 亚洲国产精久久久久久久| 亚洲精品一区中文字幕乱码| 蜜臀久久99精品久久久久久宅男| 国产精品久久久久久久一区探花| 亚洲视频999| 精品自在线视频| 91在线高清免费观看| 91香蕉国产在线观看| 91免费的视频在线播放| 成人午夜在线观看| 成人写真福利网| 亚洲春色另类小说| 日韩中文字幕av| 欧美国产日韩视频| 日韩中文有码在线视频| 国产一区二区黑人欧美xxxx| 成人午夜激情网| 中文字幕日韩欧美| 亚洲精品少妇网址| 日韩视频免费看| 国产视频观看一区| 欧美黑人性生活视频| 欧美性高跟鞋xxxxhd| 色樱桃影院亚洲精品影院| 美女扒开尿口让男人操亚洲视频网站| 欧美大尺度激情区在线播放| 亚洲国产精品一区二区久| 最新69国产成人精品视频免费| 国产精品青草久久久久福利99| 久久综合伊人77777尤物| 美女性感视频久久久| 精品国产区一区二区三区在线观看| 欧美激情啊啊啊| 久久综合88中文色鬼| 这里只有精品在线观看| 久久免费视频在线观看| 午夜免费在线观看精品视频| 欧美激情va永久在线播放| 欧美成人精品三级在线观看| 日本欧美黄网站| 欧美日本黄视频| 69久久夜色精品国产69| 亚洲美女激情视频| 成人av在线网址| 国产精品96久久久久久| 久久成人精品视频| 国产精品ⅴa在线观看h| 一本色道久久综合狠狠躁篇的优点| 亚洲一区二区三区香蕉| 亚洲美女久久久| 国产日韩欧美在线观看|