【c/c++】编写头文件

目录

(1)为什么要用头文件

(2)头文件的使用

(3)防止重复编译

(4)ifdef, ifndef和endif也可用在代码中

(5)在头文件中兼容C和C++编译器


(1)为什么要用头文件

不使用头文件,也可以编译多个源代码文件,比如有两个源代码,mymath.c test.c,像下面这样。

mymath.c

// mymath.c
// 函数的定义实现
int add(int a, int b)
{
    return a + b;
}

int max(int a, int b)
{
    return (a > b) ? a : b;
}

main.c

// main.c

#include <stdio.h>

// 函数的声明
int add(int a, int b);
int max(int a, int b);

int main()
{
    printf("%d\n", add(10, 20));
    printf("%d\n", max(10, 20));
    return 0;
}

编译和运行

[root@localhost test]# gcc mymath.c main.c -o main
[root@localhost test]# ./main
30
20
[root@localhost test]# 

对于以上例子,当外部的函数较多时,会在主代码文件main.c写较多的函数声明,使得主代码文件比较混乱,不方便代码的阅读和管理。因此需要头文件来专门统一管理函数等声明。

(2)头文件的使用

如果把函数原型放在一个头文件里,那么就不必每次使用函数时都声明其原型了。 把函数声明放入头文件是很好的习惯。
  • .c文件里放的是函数的定义
  • .h文件里面给方的是函数的声明

mymath.c

// mymath.c
// 函数的定义实现
int add(int a, int b)
{
    return a + b;
}

int max(int a, int b)
{
    return (a > b) ? a : b;
}

mymath.h

// mymath.h
int add(int a, int b);
int max(int a, int b);

main.c

#include <stdio.h>
#include "mymath.h"

int main()
{
    printf("%d\n", add(10, 20));
    printf("%d\n", max(10, 20));
    return 0;
}

编译和执行

gcc -o main main.c mymath.c
./main

(3)防止重复编译

对于刚才的mymath.h,如果在主文件中多次导入头文件,像下面这样,则会出现重复编译,带来相关问题

  1. 重复定义:同一个变量或函数在多个源文件中被重复定义,导致链接错误。
  2. 不必要的编译开销:每次包含头文件时,相关的代码会被重复编译多次。
  3. 依赖关系错误:若头文件依赖其他头文件,而这些依赖没有通过#include指令显式声明,可能会引发编译错误。
#include <stdio.h>
#include "mymath.h"
#include "mymath.h"
#include "mymath.h"

int main()
{
    printf("%d\n", add(10, 20));
    printf("%d\n", max(10, 20));
    return 0;
}

解决办法是在头文件中添加ifdef, ifndef和endif语句。#ifndef是个预编译指令,代表只要定义个常量,那么就预编译下面的代码。

#ifdef 宏
代码
#endif

头文件这样操作

// mymath.h
#ifndef __MYMATH_H__
#define __MYMATH_H__

int add(int a, int b);
int max(int a, int b);

#endif

也可以使用#pragma once

// mymath.h
#pragma once

int add(int a, int b);
int max(int a, int b);

(4)ifdef, ifndef和endif也可用在代码中

ifdef, ifndef和endif用在代码中提高兼容性或者方便调试

#include <stdio.h>
#include "mymath.h"

//#define TEST //定义一个宏,但没有任何值

int main()
{
    #ifdef TEST
    //如果定义了TEST这个宏
    //那么在预编译时会预编译 #ifdef TEST 和 #endif 之间的代码
    printf("hello world 1\n");
    #endif

    printf("%d\n", add(10, 20));
    printf("%d\n", max(10, 20));

    #ifndef TEST
    //如果没有定义TEST这个宏
    //那么在预编译时会预编译 #ifdef TEST 和 #endif 之间的代码
    printf("hello world 2\n");
    #endif
    
    return 0;
}

(5)在头文件中兼容C和C++编译器

示例头文件

//头文件函数声明
//防止头文件重复包含
#pragma once

//兼容C++编译器
//如果是C++编译器,则按c标准编译
#ifdef __cplusplus
extern "C"
{
#endif


int add(int a, int b);
int max(int a, int b);


#ifdef __cplusplus
}
#endif

#ifdef __cplusplus //如果是在c++编译器中,则会生成 __cplusplus 这个宏常量

extern "C" {/*....*/}后,会指示编译器这部分代码按C语言的进行编译,而不是C++的

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值