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
f1.h
test.c
- #include <stdio.h>
-
- #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 <stdio.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <poll.h>
- #include <string.h>
- #include <time.h>
- #include <errno.h>
-
- #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 < setsize; 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 <sys/epoll.h>
-
- 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还没有声明,从而陷入错误。
|