【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,如果在主文件中多次导入头文件,像下面这样,则会出现重复编译,带来相关问题
- 重复定义:同一个变量或函数在多个源文件中被重复定义,导致链接错误。
- 不必要的编译开销:每次包含头文件时,相关的代码会被重复编译多次。
- 依赖关系错误:若头文件依赖其他头文件,而这些依赖没有通过
#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++的
原文地址:https://blog.csdn.net/hutaotaotao/article/details/137966421
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!