打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C语言不要重复包含.h头文件和.c文件

http://blog.csdn.net/unix21/article/details/8450235

2012

1.不要重复包含头文件



--以上出自《C语言程序设计:现代方法(第2版)》

f3.h

  1. //#ifndef AE_OK  
  2. #define AE_OK 0  
  3. typedef int        ngx_int_t;  
  4. //#endif  

f2.h

  1. #include "f3.h"  

f1.h

  1. #include "f3.h"  

test.c

  1. #include <stdio.h>  
  2.   
  3. #include "f1.h"  
  4. #include "f2.h"  
  5.   
  6. int main(){  
  7.     ngx_int_t a1=1;  
  8.     printf("%d",AE_OK);  
  9.     printf("%d",a1);  
  10.     return 0;  
  11. }  

编译不过去:

导出预编译文件:

  1. ...以上省略  
  2. # 2 "test.c" 2  
  3.   
  4. # 1 "f1.h" 1  
  5. # 1 "f3.h" 1  
  6.   
  7.   
  8. typedef int ngx_int_t;  
  9. # 1 "f1.h" 2  
  10. # 4 "test.c" 2  
  11. # 1 "f2.h" 1  
  12. # 1 "f3.h" 1  
  13.   
  14.   
  15. typedef int ngx_int_t;  
  16. # 1 "f2.h" 2  
  17. # 5 "test.c" 2  
  18.   
  19. int main(){  
  20.  ngx_int_t a1=1;  
  21.  printf("%d",0);  
  22.  printf("%d",a1);  
  23.  return 0;  
  24. }  

如果我们在f3.h中增加#ifndef就不会出问题了,直接导出预编译文件:

  1. # 2 "test.c" 2  
  2.   
  3. # 1 "f1.h" 1  
  4. # 1 "f3.h" 1  
  5.   
  6.   
  7. typedef int ngx_int_t;  
  8. # 1 "f1.h" 2  
  9. # 4 "test.c" 2  
  10. # 1 "f2.h" 1  
  11. # 5 "test.c" 2  
  12.   
  13. int main(){  
  14.  ngx_int_t a1=1;  
  15.  printf("%d",0);  
  16.  printf("%d",a1);  
  17.  return 0;  
  18. }  


2. .c文件编译注意不要重复引入

这个是我从redis源码中抽取其事件库的编译

在redis源码的ae.c文件:

  1. #include <stdio.h>  
  2. #include <sys/time.h>  
  3. #include <sys/types.h>  
  4. #include <unistd.h>  
  5. #include <stdlib.h>  
  6. #include <poll.h>  
  7. #include <string.h>  
  8. #include <time.h>  
  9. #include <errno.h>  
  10.   
  11. #include "ae.h"  
  12. #include "zmalloc.h"  
  13. #include "config.h"  
  14.   
  15. /* Include the best multiplexing layer supported by this system. 
  16.  * The following should be ordered by performances, descending. */  
  17. #ifdef HAVE_EVPORT  
  18. #include "ae_evport.c"  
  19. #else  
  20.     #ifdef HAVE_EPOLL  
  21.     #include "ae_epoll.c"  
  22.     #else  
  23.         #ifdef HAVE_KQUEUE  
  24.         #include "ae_kqueue.c"  
  25.         #else  
  26.         #include "ae_select.c"  
  27.         #endif  
  28.     #endif  
  29. #endif  
  30.   
  31. aeEventLoop *aeCreateEventLoop(int setsize) {  
  32.     aeEventLoop *eventLoop;  
  33.     int i;  
  34.   
  35.     if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;  
  36.     eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);  
  37.     eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);  
  38.     if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;  
  39.     eventLoop->setsize = setsize;  
  40.     eventLoop->lastTime = time(NULL);  
  41.     eventLoop->timeEventHead = NULL;  
  42.     eventLoop->timeEventNextId = 0;  
  43.     eventLoop->stop = 0;  
  44.     eventLoop->maxfd = -1;  
  45.     eventLoop->beforesleep = NULL;  
  46.     if (aeApiCreate(eventLoop) == -1) goto err;  
  47.     /* Events with mask == AE_NONE are not set. So let's initialize the 
  48.      * vector with it. */  
  49.     for (i = 0; i < setsize; i++)  
  50.         eventLoop->events[i].mask = AE_NONE;  
  51.     return eventLoop;  
  52.   
  53. err:  
  54.     if (eventLoop) {  
  55.         zfree(eventLoop->events);  
  56.         zfree(eventLoop->fired);  
  57.         zfree(eventLoop);  
  58.     }  
  59.     return NULL;  
  60. }  

HAVE_EPOLL是前面定义的:

  1. /* Test for polling API */  
  2. #ifdef __linux__  
  3. #define HAVE_EPOLL 1  
  4. #endif  

在ae_epoll.c中的aeApiCreate函数

  1. #include <sys/epoll.h>  
  2.   
  3. typedef struct aeApiState {  
  4.     int epfd;  
  5.     struct epoll_event *events;  
  6. } aeApiState;  
  7.   
  8. static int aeApiCreate(aeEventLoop *eventLoop) {  
  9.     aeApiState *state = zmalloc(sizeof(aeApiState));  
  10.   
  11.     if (!state) return -1;  
  12.     state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);  
  13.     if (!state->events) {  
  14.         zfree(state);  
  15.         return -1;  
  16.     }  
  17.     state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */  
  18.     if (state->epfd == -1) {  
  19.         zfree(state->events);  
  20.         zfree(state);  
  21.         return -1;  
  22.     }  
  23.     eventLoop->apidata = state;  
  24.     return 0;  
  25. }  

我想抽取出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还没有声明,从而陷入错误。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Redis为什么这么快?
【作者面对面问答】包邮送《Redis 5设计与源码分析》5本
Redis源码解析(1)
为什么 Redis 单线程能支撑高并发?
Nginx学习之七
linux服务器开发浅谈
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服