C語(yǔ)言關(guān)于include順序不同導(dǎo)致編譯結(jié)果不同的問(wèn)題
今天遇到了因?yàn)閕nclude順序不同而編譯結(jié)果不同的問(wèn)題。歸根結(jié)底還是自己寫代碼的習(xí)慣不好導(dǎo)致的。
編譯環(huán)境
既然要寫就多寫點(diǎn)吧。最近又開始做TI的DSP C6455相關(guān)的開發(fā)了。之前的文章里有寫到,TI提供有一個(gè)CSL庫(kù),但是比較老,輸出的格式是COFF,而現(xiàn)在一般是ELF。如果做一些新的開發(fā)的話,建議重新編譯CSL庫(kù),并選擇輸出為ELF格式。
C6000 DSP的編譯工具鏈目前主要有7.4和8.3版本。8.0以上的版本不再支持C6455了,所以我目前用的CGT版本是7.4.24,7.4版本的應(yīng)該都差不多,因?yàn)槲臋n都是一樣的。
問(wèn)題簡(jiǎn)化
實(shí)際工程中包含大大小小的文件很多,頭文件的include層層嵌套。所以我在這里為了說(shuō)明關(guān)鍵問(wèn)題,把我實(shí)際遇到的問(wèn)題做了簡(jiǎn)化。整個(gè)工程包含三個(gè)文件main.cpp, CData.cpp和CData.hpp。源碼如下:
// main.cpp /* Scenario 1: it doesn't work */ #include "csl_types.h" #include "CData.hpp" /* Scenario 2: it does work */ // #include "CData.hpp" // #include "csl_types.h" int main(void) { return 0; }
// CData.cpp #include "CData.hpp"
// CData.cpp #ifndef CDATA_HPP_ #define CDATA_HPP_ #include <assert.h> #include <stdlib.h> class CData { public: CData(): m_pData(NULL), m_nCnt(0) {} CData(int nCnt): m_nCnt(nCnt) { m_pData = new int[nCnt]; assert(m_pData != NULL); } ~CData(){ if(m_pData){ delete[] m_pData; m_pData = NULL; } } protected: int *m_pData; int m_nCnt; }; #endif
實(shí)際上的現(xiàn)象就是main.cpp中include了兩個(gè)頭文件,它們include的前后順序不同,導(dǎo)致了編譯結(jié)果不同。在第一種情況下編譯得到這樣的結(jié)果:
而在第二種情況下就是能夠正常完成編譯。
問(wèn)題分析
a value of type "void *" cannot be used to initialize an entity of type "int *"
a value of type "void *" cannot be assigned to an entity of type "int *"
報(bào)錯(cuò)提示的問(wèn)題和NULL有關(guān),大概意思是NULL是一個(gè)void *的類型,不能把它賦給其他類型的變量。但可以看到,單獨(dú)編譯CData.cpp是沒有出現(xiàn)問(wèn)題的。而在編譯main.cpp的時(shí)候,因?yàn)橄萯nclude了csl_types.h,導(dǎo)致改變了NULL的定義,所以出了問(wèn)題。
查找有NULL相關(guān)的定義的文件可以找到:
// stdlib.h #ifndef NULL #define NULL 0 #endif
// csl_types.h #ifndef NULL #define NULL ((void*)0) #endif
// xdc/std.h #undef NULL #if defined(__cplusplus) || !defined(xdc__strict) #define NULL 0 #else #define NULL ((void *)0) #endif
stdlib.h大家應(yīng)該都比較熟悉,是標(biāo)準(zhǔn)庫(kù)。csl_types.h是在用CSL的時(shí)候會(huì)不經(jīng)意間包含的一個(gè)頭文件。還有xdc/std.h是在用RTSC時(shí)可能會(huì)用到的頭文件。這幾個(gè)文件里都有關(guān)于NULL的定義。
我這次遇到的問(wèn)題就是因?yàn)榍皟蓚€(gè)文件include的前后順序不同,NULL定義的情況也就不同了。而第三個(gè)文件感覺比較好,會(huì)先undef NULL,然后再重新define,應(yīng)該可以一定程度上避免這個(gè)問(wèn)題。但是第三個(gè)文件中有些類型的定義也會(huì)和csl_types.h產(chǎn)生沖突,所以用起來(lái)還是要注意。
總結(jié)
這次雖然兩個(gè)頭文件include的順序引發(fā)的問(wèn)題。但是歸根結(jié)底我覺得還是因?yàn)槲抑苯釉陬^文件里做類(CData)的定義,而沒有把定義放在cpp文件中。如果把方法的具體實(shí)現(xiàn)放在源文件里,然后把那些頭文件中的include放到源文件里去,應(yīng)該可以一定程度上避免這種問(wèn)題的出現(xiàn)。
實(shí)際工程中遇到這類問(wèn)題,往往include有多層,很難發(fā)現(xiàn),所以還是應(yīng)該要有一個(gè)良好的編程習(xí)慣!
到此這篇關(guān)于C語(yǔ)言關(guān)于include順序不同導(dǎo)致編譯結(jié)果不同的問(wèn)題的文章就介紹到這了,更多相關(guān)C語(yǔ)言include順序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02C++中為何推薦要把基類析構(gòu)函數(shù)設(shè)置成虛函數(shù)
這篇文章主要介紹了C++中為何推薦要把基類析構(gòu)函數(shù)設(shè)置成虛函數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

C語(yǔ)言函數(shù)基礎(chǔ)教程分類自定義參數(shù)及調(diào)用示例詳解

VC使用TerminateProcess結(jié)束進(jìn)程實(shí)例

C++中關(guān)于多態(tài)實(shí)現(xiàn)和使用方法

基于OpenCV實(shí)現(xiàn)車道線檢測(cè)(自動(dòng)駕駛 機(jī)器視覺)