html引用c 變量,Y.A.K.E

記錄一次C++項目改造中定義全局變量的操作.

我對C/c++不太熟悉,在修改別人項目的時候,想弄個文件,專門存放全局變量.

然后各種不對.

xxx previously defined here錯誤 或者 error: redefinition of xxx或者initialized and declared 'extern'

反正各種問題.

其實根本原因就是重復引用導致的.

include引用

include 包含一個.h文件,簡單理解就是:

將.h文件的內容直接插入到當前位置.

如果

main.c 引入 a.h 和? b.h

而b.h 因為需要調用a.h一些變量,必須也要引用a.h

那么最后,合并的mian.c大致內容:

a.h內容 (main.c引入)

a.h內容(b.h引入)

b.h內容 (main.c引入)

main.c (除了include外的內容)

這樣a.h的內容出現了兩次.就會出現編譯錯誤.

因為正常情況下,變量和函數都不能重復定義.

對于這種問題,解決比較簡單.

宏條件語句

比如a.h文件大致內容:

#ifndef HEADER__A_H

#define HEADER__A_H

//代碼

#endif

宏條件語句會在編譯前進行預處理.

如果沒有定義"HEADER__A_H"的時候,

定義下"HEADER__A_H",并插入代碼.

如果"HEADER__A_H"已經定義,將不滿足宏條件, 所以#ifndef? 到 #endif內容全部會忽略.

所以,只會在第一次引入的時候滿足宏條件.

再回到上面的main.c 預處理后 :

a.h內容 (main.c引入,并定義了"HEADER__A_H")

a.h內容(b.h引入,內容是空的.)

b.h內容 (main.c引入)

main.c (除了include外的內容)

因為第一次引入a.h的時候,定義了"HEADER__A_H"宏,所以,之后再調用.a.h都不會觸發宏條件語句為"true"的情況.

所以只有第一次引入a.h的時候,會插入a.h內容.

之后再引用a.h的時候因為宏條件語句無法滿足,所以后面插入的內容是空的.

即使這樣還是會出現變量,或者函數重復定義的情況.然后我再補充下C/c++項目編譯過程.

編譯過程

一個項目多有多個.c/.cpp文件.

編譯過程是

gcc 分別編譯每個.c/.cpp文件.編譯成.o文件

然后

ld 鏈接這些.o文件.編譯成最終可執行文件.

重點是分別兩個字.

假設

main.c 引入 a.h

m2.c 也引入a.h

因為main.c和m2.c兩個文件時分別編譯的.

所以編譯出來的

main.o 和m2.o 兩個文件都會完整的引入并一起編譯a.h內容.

ld鏈接這些.o文件的時候,.就有相同的標簽(匯編的全局標簽),導致鏈接失敗.

C語言當初設計了一個關鍵詞專門來解決這種問題.

extern

extern 后面跟著函數原型,或者變量定義.

例子

extern int abc;

extern void test(int code);

作用就是騙編譯器.告訴編譯器,這個變量,或者函數在其他地方已經定義了.

讓編譯器不再重新定義.這樣避免最后ld鏈接的時候,找到相同的標簽導致鏈接失敗.

extern 的變量和函數可以多次聲明.但是一定要有一個原始聲明.

extern 是"假聲明",你必須要有個"真聲明".才能ld鏈接成功.

搞懂這些,就搞懂了為啥會重復引用了.

推薦操作

也就是項目全局變量定義的方法,規避重復引用的辦法.

config.c

我們將全局變量聲明放這里.這里是"真聲明" .

// config.c

//引入它同名的頭文件

#include "config.h"

//定義變量,并給初始值

int abc=123;

//僅定義變量,不給初始值.

bool test;

//定義函數

int mAdd(int a,int b) {

return a+b;

}

config.h

config.h文件然后將c聲明的變量復制一份.然后分別加上extern標識符即可.

切記. extern后跟著的變量不要用等號進行賦值.

#ifndef CONFIG_H

#define CONFIG_H

// config.h

//嚴禁對變量初始化

// 錯誤 → extern int abc=123;

//正確 ↓

extern int abc;

extern bool test;

//類似函數原型.

extern int mAdd(int a, int b);

#endif // CONFIG_H

其他.c/.cpp/.h文件只要大膽的引用config.h 注意是H文件.即可完美的處理.

分析

舉例5個文件

main.c?? 主函數

m2.c?? 自寫的邏輯算法庫

m2.h?? 邏輯算法庫函數的聲明(函數原型)

config.c? 全局變量聲明

config.h?? 給每個全局變量加上extern關鍵詞

main.c 引用 m2.h 和config.h?? ,其中m2.h中也引入了config.h

m2.c 引用了 m2.h 和config.h

config.c 引用了 config.h

編譯流程

實際上就是gcc編譯三個.c文件.然后將編譯出來三個.文件鏈接成可執行文件.

推導

假設,先gcc編譯main.c

那么預處理后

config.h內容 (main.c引入)

config.h內容(由m2.h引入,內容是空的.)

m2.h內容 (main.c引入)

main.c (除了include外的內容)

所以它能成功編譯成main.o文件.

同理

gcc編譯 m2.c

它的h沒有互相引用,這個不用解釋,只要沒有語法錯誤,直接編譯出m2.o文件

再同理可以推

gcc編譯 config.c? 也是直接編譯成config.o文件

鏈接

重點是鏈接

main.o 引用的config.h用的extern ,沒有分配標簽.沒有原始地址,但是鏈接器忽略錯誤,

m2.o 也引用了config.h,也是extern ,沒有分配標簽.沒有原始地址,但是鏈接器忽略錯誤,

然后是config.o 也引用了config.h 這里extern所以也是忽略的.重點是.config.c是原始分配了標簽.有變量原始地址.

所以ld鏈接器讓main.o 和m2.o(變量)標簽在config.o找到了原始地址.

鏈接成功.編譯出可執行文件.

總結

config.c 文件放變量

config.h 用宏條件指令防止重復包含. 然后對config.c變量做extern 額外聲明.

其他的c或者h文件只需要#include "config.h" 就可以調用全局變量.

這樣就不會出現重復定義,或者重復引用

遺留問題

extern 和 inline 關鍵詞組合描述函數的時候,

正常庫內,或者自己內部調用沒問題.

在跨庫的時候有問題.

參考

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271552.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271552.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271552.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux python開發環境_如何在Linux系統中搭建Python編程環境

1 在大多數的Linux系統中,基本上都默認安裝了Python,也就是說,在Linux的系統中基本上是不需要安裝什么軟件,就可以使用Python。 下面以ubuntu操作系統為例,看看如何在Linux操作系統中搭建Python編程環境。2 檢查Ubuntu…

CentOS 搭建 LAMP服務器

CentOS 7.0默認使用的是firewall作為防火墻,這里改為iptables防火墻。 1、關閉firewall: systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewall開機啟動 2、安裝iptables防火墻 yum install iptables-ser…

什么叫兜底條款

就是一個條款就能覆蓋所有未說到的內容:如:"其它應當受到處罰的行為." 有了這樣的條款,制度和法律才不會出現死角,讓一些人鉆空子,由于規定不可能十分周全,所心好多人還是在想方設法鉆空子.

當你的電腦C盤滿了怎么辦?這兩種方法都能解決

用了好幾年的電腦,在分區的時候C盤空間分的太小;有的喜歡把下載的軟件、工作時的文件都放在桌面上方便自己使用;有的安裝軟件的時候不選擇安裝目錄或一些軟件必須要安裝在C盤,這樣你的C盤的空間就會變得不夠,今天分享下…

一個html有幾個css,幾個CSS的黑科技_html/css_WEB-ITnose

原文出處: JellyBool(JellyBool) 歡迎分享原創到伯樂頭條昨天由于某些原因沒有寫博客,之前說好的每天一篇的,這篇是為了補昨天的了。然后我就要當一次標題黨了。這里的黑科技其實就是一些CSS中不怎么為人所知但在解決某些問題的時候很溜的屬性…

python遞歸函數講解_帶你深入學習Python——Python遞歸詳解!

一、遞歸 遞歸:在調用一個函數的過程中,直接或間接地調用了函數本身這個就叫遞歸 注:Python在遞歸中沒有像別的語言對遞歸進行優化,所以他的每一次調用都會基于上一次的調用進行,并且他設置了最大的遞歸數量防止遞歸外溢 遞歸調用…

51nod 1040最大公約數和(歐拉函數)

1040 最大公約數之和題目來源: rihkddd基準時間限制:1 秒 空間限制:131072 KB 分值: 80 難度:5級算法題收藏關注給出一個n,求1-n這n個數,同n的最大公約數的和。比如:n 61,2,3,4,5,6 同6的最大公…

計算機安全基礎:加密技術知識筆記

1、加密技術介紹 加密技術是最常用的數據安全保密的手段,加密技術的關鍵在于加密/解密算法和密鑰管理。 數據加密的過程:對明文文件或數據按照某種算法進行處理,變成密文。密文需要根據相應的密鑰才能獲得原來的明文信息,通過這種…

an導入html5,H5-FLASH:AN HTML5-BASED FLASH RUNTIME

摘要:Flash has been widely deployed to many internet applications.Nevertheless,as a closed development platform,there are more and more concerns arisen around its security and performance problems.On the other hand,HTML5 provides an alternative …

JAVA 獲取格林威治時間(GMT)

記錄下獲取GMT時間的方法: //格式可根據需要自定義,如yyyy-MM-dd HH:mm:ss 等等 SimpleDateFormat sdf new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss GMT", Locale.US); Calendar calendar Calendar.getInstance(); sdf.setTimeZone(Tim…

Linux CentOS下安裝Oracle

1 、在安裝oracle之前首先安裝以下組件包,直接輸入下列語句安裝。 yum install binutils* -y yum install compat-lib* -y yum install gcc* -y yum install glibc* -y yum install ksh* -y yum install libgcc* -y yum install libstdc* -y yum install libaio* -y…

計算機安全基礎:認證技術知識筆記

1、認證技術介紹 認證技術主要是用來解決網絡通信過程中通信雙方身份的認可。認證的過程涉及加密和密鑰交換。認證方一般都會有賬戶名、口令、使用摘要算法和基于PKI認證。 2、PKI系統介紹 PKI是一種遵循既定標準的密鑰管理平臺,能夠為所有的網絡應用提供加密和數字…

python 比例之差z假設檢驗_假設檢驗在數據分析中的應用

前言Z檢驗T檢驗獨立樣本t檢驗配對樣本t檢驗單樣本t檢驗前言在這篇文章中,我不會具體去推導檢驗統計量和相應拒絕域的得出,這對于大部分非統計學專業的人士來說是晦澀的,我只想通過一個案例告訴大部分初學者假設檢驗怎么在數據挖掘中使用。%ma…

中南民族大學計算機類有什么具體專業,中南民族大學計算機科學學院計算機科學與技術專業簡介...

計算機科學與技術專業計算機科學與技術專業1985年開始招收本科生。1989年開設計算機應用專業。1998年教育部進行專業調整,成立了計算機科學與技術專業。2012年,計算機科學與技術專業獲得校級品牌專業稱號。計算機科學與技術專業師資雄厚,結構…

Java實現字母的大小寫轉換

String result1 "JAVA";String result2 "springcloud";/*** toLowerCase()* 大寫轉小寫*/System.out.println(result1.toLowerCase());/*** 小寫轉大寫* toUpperCase()*/System.out.println(result2.toUpperCase()); 運行截圖如下:

iOS開發tableview二級聯動的細節實現中注意的細節總結

首先說網絡慢帶來的數據顯示問題 可以通過判斷請求參數是否一致來刷新tableview。 SJBCategaryModel * categaryModel self.categarys[CategarySelectRow]; NSMutableDictionary * params [NSMutableDictionary dictionary]; categaryModel.currentPage 1; params["a&q…

linux ctrlc 退出循環_linux按行讀取 (while read line與forloop)

在linux下一般用while read line與for循環按行讀取文件。這兩種方法有什么區別呢&#xff1f;現有如下test.txt文件&#xff1a;1while read linewhile read line; do echo $linedone < test.txt輸出結果與上圖一致。這里也可以寫為&#xff1a;cat test.txt | while read …

計算機系統基礎:計算機可靠性知識筆記

1、計算機可靠性介紹 計算機的硬件故障通常都是由于元器件失效造成的。元器件的可靠性分為三個階段&#xff1a;開始階段元器件處于不穩定階段失效率比較高、第二階段是正常工作階段&#xff0c;失效率最低、第三階段元器件開始老化&#xff0c;失效率就又開始提高。又稱為“浴…

python時間計算_python datetime庫使用和時間加減計算

datetime庫使用 一、操作當前時間 1.獲取當前時間 >>> importdatetime>>> printdatetime.datetime.now()2019-07-11 14:24:01.954000 時間格式化輸出&#xff1a; >>> print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")2019-…

桌面計算機打開不了怎么辦,電腦桌面上的所有東西都打不開了 怎么處理

1、如果各分區下帶autorun.inf一類的隱藏文件&#xff0c;刪除后最好重新啟動電腦。2、在文件類型中重新設置打開方式(以XP為例)打開 我的電腦&#xff0d;&#xff0d;工具&#xff0d;&#xff0d;文件夾選項&#xff0d;&#xff0d;文件類型&#xff0c;找到“驅動器”或“…