c语言 自动包含头文件,C语言不要重复包含.h头文件和.c文件
http://blog.csdn.net/unix21/article/details/8450235
2012
1.不要重復包含頭文件
--以上出自《C語言程序設計:現代方法(第2版)》
f3.h
//#ifndef?AE_OK
#define?AE_OK?0
typedef?int????????ngx_int_t;
//#endif
f2.h
#include?"f3.h"
f1.h
#include?"f3.h"
test.c
#include?
#include?"f1.h"
#include?"f2.h"
int?main(){
ngx_int_t?a1=1;
printf("%d",AE_OK);
printf("%d",a1);
return?0;
}
編譯不過去:
導出預編譯文件:
...以上省略
#?2?"test.c"?2
#?1?"f1.h"?1
#?1?"f3.h"?1
typedef?int?ngx_int_t;
#?1?"f1.h"?2
#?4?"test.c"?2
#?1?"f2.h"?1
#?1?"f3.h"?1
typedef?int?ngx_int_t;
#?1?"f2.h"?2
#?5?"test.c"?2
int?main(){
ngx_int_t?a1=1;
printf("%d",0);
printf("%d",a1);
return?0;
}
如果我們在f3.h中增加#ifndef就不會出問題了,直接導出預編譯文件:
#?2?"test.c"?2
#?1?"f1.h"?1
#?1?"f3.h"?1
typedef?int?ngx_int_t;
#?1?"f1.h"?2
#?4?"test.c"?2
#?1?"f2.h"?1
#?5?"test.c"?2
int?main(){
ngx_int_t?a1=1;
printf("%d",0);
printf("%d",a1);
return?0;
}
2..c文件編譯注意不要重復引入
這個是我從redis源碼中抽取其事件庫的編譯
在redis源碼的ae.c文件:
#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?"ae.h"
#include?"zmalloc.h"
#include?"config.h"
/*?Include?the?best?multiplexing?layer?supported?by?this?system.
*?The?following?should?be?ordered?by?performances,?descending.?*/
#ifdef?HAVE_EVPORT
#include?"ae_evport.c"
#else
#ifdef?HAVE_EPOLL
#include?"ae_epoll.c"
#else
#ifdef?HAVE_KQUEUE
#include?"ae_kqueue.c"
#else
#include?"ae_select.c"
#endif
#endif
#endif
aeEventLoop?*aeCreateEventLoop(int?setsize)?{
aeEventLoop?*eventLoop;
int?i;
if?((eventLoop?=?zmalloc(sizeof(*eventLoop)))?==?NULL)?goto?err;
eventLoop->events?=?zmalloc(sizeof(aeFileEvent)*setsize);
eventLoop->fired?=?zmalloc(sizeof(aeFiredEvent)*setsize);
if?(eventLoop->events?==?NULL?||?eventLoop->fired?==?NULL)?goto?err;
eventLoop->setsize?=?setsize;
eventLoop->lastTime?=?time(NULL);
eventLoop->timeEventHead?=?NULL;
eventLoop->timeEventNextId?=?0;
eventLoop->stop?=?0;
eventLoop->maxfd?=?-1;
eventLoop->beforesleep?=?NULL;
if?(aeApiCreate(eventLoop)?==?-1)?goto?err;
/*?Events?with?mask?==?AE_NONE?are?not?set.?So?let's?initialize?the
*?vector?with?it.?*/
for?(i?=?0;?i?
eventLoop->events[i].mask?=?AE_NONE;
return?eventLoop;
err:
if?(eventLoop)?{
zfree(eventLoop->events);
zfree(eventLoop->fired);
zfree(eventLoop);
}
return?NULL;
}
HAVE_EPOLL是前面定義的:
/*?Test?for?polling?API?*/
#ifdef?__linux__
#define?HAVE_EPOLL?1
#endif
在ae_epoll.c中的aeApiCreate函數
#include?
typedef?struct?aeApiState?{
int?epfd;
struct?epoll_event?*events;
}?aeApiState;
static?int?aeApiCreate(aeEventLoop?*eventLoop)?{
aeApiState?*state?=?zmalloc(sizeof(aeApiState));
if?(!state)?return?-1;
state->events?=?zmalloc(sizeof(struct?epoll_event)*eventLoop->setsize);
if?(!state->events)?{
zfree(state);
return?-1;
}
state->epfd?=?epoll_create(1024);?/*?1024?is?just?an?hint?for?the?kernel?*/
if?(state->epfd?==?-1)?{
zfree(state->events);
zfree(state);
return?-1;
}
eventLoop->apidata?=?state;
return?0;
}
我想抽取出redis的事件庫
一開始不知道include的.c文件編譯的時候不需要重復引入,不然編譯報錯:
ae_epoll.c不用被引入,因為在ae.c已經引入了。
成功編譯:
生成了redis文件。
2..h文件編譯注意不要重復引入
報錯anet.h:47: 錯誤:expected declaration specifiers or ‘...’ before ‘size_t’
原因是anet.h頭文件重復引用,去掉anet.h,重新編譯就可以了:
原因分析:
b.h中#include "../../a.h" 而a.h中的函數聲明中用到了b.h中的結構體或者typedef,那么就會出現在包含a.h的時候b.h中的結構體或者typedef還沒有聲明,從而陷入錯誤。
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的c语言 自动包含头文件,C语言不要重复包含.h头文件和.c文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言遥控器程序,红外遥控
- 下一篇: linux盘符改名字,Linux 下po