C语言不要重复包含.h头文件和.c文件
生活随笔
收集整理的這篇文章主要介紹了
C语言不要重复包含.h头文件和.c文件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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 <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" 1typedef int ngx_int_t;
# 1 "f1.h" 2
# 4 "test.c" 2
# 1 "f2.h" 1
# 1 "f3.h" 1typedef int ngx_int_t;
# 1 "f2.h" 2
# 5 "test.c" 2int 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" 1typedef int ngx_int_t;
# 1 "f1.h" 2
# 4 "test.c" 2
# 1 "f2.h" 1
# 5 "test.c" 2int 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
#endifaeEventLoop *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還沒有聲明,從而陷入錯誤。
總結
以上是生活随笔為你收集整理的C语言不要重复包含.h头文件和.c文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汇编语言调用Linux系统调用
- 下一篇: ATT格式汇编语言