成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

函數或全局變量重復定義時會怎樣?

開發 前端
如非特殊需求,應該盡量避免出現全局變量同名,以免造成意料不到的結果,例如使用變量時最小范圍定義,即盡可能避免全局變量,或者使用命名空間(如C++中)。

 [[383839]]

 本文轉載自微信公眾號「編程珠璣」,作者守望先生。轉載本文請聯系編程珠璣(ID:shouwangxiansheng)公眾號。 

可能有些朋友第一反應是,那肯定是編譯不過嘍:

  1. // 來源:公眾號【編程珠璣】 
  2. // 作者:守望先生 
  3. // fun.c 
  4. #include<stdio.h> 
  5. void fun() 
  6.     printf("編程珠璣\n"); 
  7.  
  8. // main.c 
  9. #include<stdio.h> 
  10. void func() 
  11.     printf("公眾號\n"); 
  12. int main(void) 
  13.     func(); 
  14.     return 0; 

編譯:

  1. $ gcc -o main main.c fun.c 
  2. /tmp/ccKeACRk.o: In function `fun': 
  3. fun.c:(.text+0x0): multiple definition of `fun' 
  4. /tmp/cc4ezgqh.o:main.c:(.text+0x0): first defined here 
  5. collect2: error: ld returned 1 exit status 

可以看到這里報錯了,因為fun重復定義了。

但是重復定義就會報錯,會編譯不過嗎?不全是!

再看下面的代碼:

  1. // 來源:公眾號【編程珠璣】 
  2. // 作者:守望先生 
  3. //var.c 
  4. int num; 
  5. void change() 
  6.     num = 1023; 
  7.  
  8. //main.c 
  9. #include<stdio.h> 
  10. void change(); 
  11. int num = 1024; 
  12. int main(void) 
  13.     printf("before:num is %d\n", num); 
  14.     change(); 
  15.     printf("after:num is %d\n", num); 
  16.     return 0; 

輸出結果:

  1. before:num is 1024  
  2. after:num is 1023  

從結果中可以看到,雖然num被定義了兩次,但是仍然可以編譯通過,并且正常運行。這又是為什么呢?

符號

在說明今天重點分享的內容之前,先簡單了解一下什么是符號。在《hello程序是如何變成可執行文件的》中講到過,ELF文件生成的最后階段會經歷鏈接,而鏈接階段正是基于符號才能完成。每個目標文件都會有一個符號表。而鏈接過程正是通過符號表中的符號,將不同的目標文件“粘”在一起,形成最后的庫或者可執行文件。要查看一個目標文件的符號信息也很容易:

  1. // symbol.c 
  2. #include<stdio.h> 
  3. int symbol = 1024; 
  4. int func_symbol() 
  5.     return 0; 

編譯:

  1. $ gcc smbol.c #編譯 
  2. $ nm symbol.o #查看符號信息 
  3. 0000000000000000 T func_symbol 
  4. 0000000000000000 D symbol 

通過nm命令就可以查看符號信息,這里就有我們的func_symbol函數和全局變量symbol的符號。

關于nm的使用,在《幾個命令了解ELF文件的秘密》也有介紹。

除了上面提到的全局符號,目標文件中還有其他符號信息,不過這不是本文關注的重點。

強符號與弱符號

對于C/C++語言來說,編譯器默認函數和初始化了的全局變量為強符號,未初始化的全局變量為弱符號。當然也可以通過

  1. __attribute__((weak)) 

來定義一個強符號為弱符號。

通過下面的例子來看看哪些是強符號,哪些是弱符號:

  1. #include<stdio.h> 
  2. int weak; // 未初始化全局變量,弱符號 
  3. int strong = 1024; // 已初始化全局變量,強符號 
  4. __attribute__((weak)) int weak1 = 2222; // 使用標識修飾的弱符號 
  5. int main(void) 
  6.     printf("編程珠璣\n"); 
  7.     return 0; 

注意,這里的強符號與弱符號都是針對定義來說的。

同名時,用哪個?

對于多重定義,即標題提到的變量重名時,鏈接器有它的處理規則:

  • 1.強符號不允許重復
  • 2.有一個強符號和多個弱符號,使用強符號
  • 3.多個弱符號,則隨意選擇一個

關于第一點,在最開始的例子中你已經見到了,最常見的情況就是你重復定義了變量或者函數等等。

而第二點也有示例,示例中,雖然定義了兩個num,但是var.c中未初始化的num是弱符號,main.c中的num是強符號,這種情況下編譯正常。只是最終會使用強符號的num。

再看一個第三點的例子也是類似,當其中main.c的num無初始化時,也是可以編譯過的。這種情況下的誤用也就罷了,如果是重復的符號,但是類型不同,問題就更大了,即var.c的內容如下:

  1. //var.c 
  2. double num; 
  3. void change() 
  4.     num = 1023; 

這里的num變成了double,再次編譯運行,你會發現意想不到的結果:

  1. before:num is 1024  
  2. after:num is 0  

為什么修改后是0?原因在于double類型的數據存儲與int類型數據存儲格式不一樣(參考《對浮點數的一些理解》),且它們占用空間長度都不一樣,在本文例子中,double占用8字節,而int占用4字節。

總之,這不是我們想要的結果,最終的后果可能比我們想象的要嚴重,要更難發現。

總結

如非特殊需求,應該盡量避免出現全局變量同名,以免造成意料不到的結果,例如使用變量時最小范圍定義,即盡可能避免全局變量,或者使用命名空間(如C++中)。

當然了,強弱符號在某些時候是非常有用的,例如制作庫以支持用戶自定義的庫,這又該怎么做呢?敬請期待下一篇。

參考

參考書籍

《深入理解計算機系統》

《程序員的自我修養》

 

責任編輯:武曉燕 來源: 編程珠璣
相關推薦

2009-12-04 13:14:19

PHP Global變

2010-11-12 10:08:55

SQL Server全

2013-07-25 15:15:26

iOS開發學習iOS全局變量

2013-07-17 16:16:06

Android全局變量定義全局變量Application

2025-06-03 08:50:00

Static全局變量C 語言

2010-03-09 14:12:55

Python全局變量

2013-07-22 14:07:47

2009-09-24 09:28:00

Scala講座全局變量scala

2009-11-06 13:28:19

Javascript框

2009-12-09 17:07:08

PHP unset全局

2010-02-01 14:28:37

Python全局變量

2015-01-07 14:41:32

Android全局變量局部變量

2024-05-29 08:49:22

Python全局變量局部變量

2009-12-04 13:31:21

PHP全局變量不能生效

2017-02-08 12:28:37

Android變量總結

2018-05-14 09:15:24

Python變量函數

2014-06-23 10:25:12

2010-09-08 17:25:17

SQL全局變量

2022-11-28 11:15:20

Tomcat回顯方式

2011-08-23 13:54:10

LUA全局變量
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕乱码一区二区三区 | 三级成人在线观看 | 国产精品入口久久 | 欧美日日 | 亚洲一区二区三区在线视频 | 日韩美女一区二区三区在线观看 | 99久久国产综合精品麻豆 | 国产一区二区中文字幕 | 国产日韩精品一区二区 | 一级毛片大全免费播放 | 国产一级在线 | 精品网| 成人午夜电影网 | 色婷婷国产精品综合在线观看 | 日韩视频一区 | av一二三区 | 久久综合av | 国产一区在线免费 | 91tv在线观看| 激情 婷婷 | 日韩精品一区二区在线观看 | 精品毛片 | 瑟瑟视频在线看 | 欧美a在线看 | 逼逼网 | 久久久久国产一级毛片 | 成人视屏在线观看 | 范冰冰一级做a爰片久久毛片 | 亚洲三级国产 | 国产清纯白嫩初高生视频在线观看 | 国产日韩欧美精品一区二区三区 | 中文字幕日韩一区二区 | 在线观看亚 | 国产精品欧美一区二区三区 | 羞羞视频免费在线观看 | 亚洲欧洲日本国产 | 中文字幕免费在线 | 超碰免费在 | 日本精品免费 | 亚洲精品在线播放 | 亚洲国产第一页 |