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

15 篇文章 0 订阅
4 篇文章 0 订阅

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" 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还没有声明,从而陷入错误。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值