/unix21/article/details/8450235
1.不要重复包含头文件
--以上出自《C语言程序设计:现代方法(第2版)》
f3.h
//#ifndefAE_OK
#defineAE_OK0
typedefintngx_int_t;
//#endif
f2.h
#include"f3.h"
f1.h
#include"f3.h"
test.c
#include
#include"f1.h"
#include"f2.h"
intmain(){
ngx_int_ta1=1;
printf("%d",AE_OK);
printf("%d",a1);
return0;
}
编译不过去:
导出预编译文件:
...以上省略
#2"test.c"2
#1"f1.h"1
#1"f3.h"1
typedefintngx_int_t;
#1"f1.h"2
#4"test.c"2
#1"f2.h"1
#1"f3.h"1
typedefintngx_int_t;
#1"f2.h"2
#5"test.c"2
intmain(){
ngx_int_ta1=1;
printf("%d",0);
printf("%d",a1);
return0;
}
如果我们在f3.h中增加#ifndef就不会出问题了,直接导出预编译文件:
#2"test.c"2
#1"f1.h"1
#1"f3.h"1
typedefintngx_int_t;
#1"f1.h"2
#4"test.c"2
#1"f2.h"1
#5"test.c"2
intmain(){
ngx_int_ta1=1;
printf("%d",0);
printf("%d",a1);
return0;
}
2..c文件编译注意不要重复引入
这个是我从redis源码中抽取其事件库的编译
在redis源码的ae.c文件:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"ae.h"
#include"zmalloc.h"
#include"config.h"
/*Includethebestmultiplexinglayersupportedbythissystem.
*Thefollowingshouldbeorderedbyperformances,descending.*/
#ifdefHAVE_EVPORT
#include"ae_evport.c"
#else
#ifdefHAVE_EPOLL
#include"ae_epoll.c"
#else
#ifdefHAVE_KQUEUE
#include"ae_kqueue.c"
#else
#include"ae_select.c"
#endif
#endif
#endif
aeEventLoop*aeCreateEventLoop(intsetsize){
aeEventLoop*eventLoop;
inti;
if((eventLoop=zmalloc(sizeof(*eventLoop)))==NULL)gotoerr;
eventLoop->events=zmalloc(sizeof(aeFileEvent)*setsize);
eventLoop->fired=zmalloc(sizeof(aeFiredEvent)*setsize);
if(eventLoop->events==NULL||eventLoop->fired==NULL)gotoerr;
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)gotoerr;
/*Eventswithmask==AE_NONEarenotset.Solet'sinitializethe
*vectorwithit.*/
for(i=0;i
eventLoop->events[i].mask=AE_NONE;
returneventLoop;
err:
if(eventLoop){
zfree(eventLoop->events);
zfree(eventLoop->fired);
zfree(eventLoop);
}
returnNULL;
}
HAVE_EPOLL是前面定义的:
/*TestforpollingAPI*/
#ifdef__linux__
#defineHAVE_EPOLL1
#endif
在ae_epoll.c中的aeApiCreate函数
#include
typedefstructaeApiState{
intepfd;
structepoll_event*events;
}aeApiState;
staticintaeApiCreate(aeEventLoop*eventLoop){
aeApiState*state=zmalloc(sizeof(aeApiState));
if(!state)return-1;
state->events=zmalloc(sizeof(structepoll_event)*eventLoop->setsize);
if(!state->events){
zfree(state);
return-1;
}
state->epfd=epoll_create(1024);/*1024isjustanhintforthekernel*/
if(state->epfd==-1){
zfree(state->events);
zfree(state);
return-1;
}
eventLoop->apidata=state;
return0;
}
我想抽取出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还没有声明,从而陷入错误。