C语言的头文件和宏定义详解
头文件
头文件,顾名思义就是定义在C语言文件头部的那一坨东西
#include <stdio.h>
这就是一个标准输入输出的头文件声明,头文件声明写在定义文件(后缀名.c的文件)的头部,并在定义文件中具体实现
#include <stdlib.h>
#include "mylib.h"
这是两种声明头文件的方法,其中尖括号表示“到环境指定的目录去引用”,而双引号表示“首先在当前目录查找,然后在到环境指定的目录去引用”
在C表准库中每个库函数都在一个头文件中声明,可以通过第一种方式引用
头文件的格式
#ifndef _MYLIB_H_
#define _MYLIB_H_
...
#endif
第一句“ifndef”意思是“如果在导入头文件的文件中之前没有导入该头文件就编译下面的代码”,该句的作用是防止重复导入
第二句“define”是“宏定义”的意思,表示以下代码是的头文件主体部分
最后来一句“endif”和“ifdef”首尾呼应
其中“ifndef”和“define”后面跟的是相同的“标识”,通常和头文件名相同,所有字母均大写并把点号改为下划线即可
#include "mylib.h"
看到这句话后编译器会把该头文件“mylib.h”复制粘贴到导入的文件中,之后你就可以使用头文件中定义的常量和结构定义了
显然恰当地使用头文件有利于更好的组织文件和项目
提请注意
1. 头文件只是声明,不占内存;在编译时会被合并到源文件
2. 头文件和其它C语言文件一样可以引用其它文件,可以写预处理块但是不要出现具体语句
3. 可以在头文件中定义宏函数,其本质上还是一个声明
4. 各个头文件相互独立,标准头文件之间不存在相互包含关系
5. 头文件可以重复引用,但是相当于只导入一次
6. 从C语法角度讲完全可以在头文件中写任何东西,因为#include
在作用上和Ctrl-C + Ctrl-V
等效——但是这样时不推荐的;头文件的作用就是更好的组织代码
何时使用
1. 结构体的定义
2. 函数声明,变量声明,宏定义,常数定义等
3. 当源代码不便公布时使用头文件提供接口
4. 在大项目中需要多文件联合编译
小栗子
#ifndef _NODE_H_
#define _NODE_H_typedef struct _node{int value;struct _node *next;
}Node;#endif
#include "node.h"
int main(int argc, char const argv[])
{Node *p=(Node*)malloc(sizeof(Node));...return 0;
}
常用头文件
stdio.h 标准输入输出
stdlib.h 标准常用库
string.h 字符串函数库
math.h 数学库
ctype.h 字符函数库
time.h 时间库
windows.h 微软视窗库
宏定义
宏定义是C语言提供的三种预处理功能的其中一种,这三种预处理包括:宏定义、文件包含、条件编译。宏定义和操作符的区别是:宏定义是替换,不做计算,也不做表达式求解。
“宏定义”也称“宏替换”,“宏”
#define PI 3.1415926
这就是一个简单的宏,在程序的预处理阶段宏名会被替换为后面的字符串
传入参数的宏
1. #:字符串化操作,即将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串,使用时置于宏定义体中的参数名前,如:
#define func(para) #para
...
char str[]=func(hello); //被展开为:char str[]="hello"
说明:如果传入的参数之前有空格则忽略之,如果参数之间有多个空格则在连成字符串时只算一个
2. #@:字符化操作,即将宏定义传入的参数名转换为用一对单引号扩起来的参数名字符串,使用时置于参数名前,如:
#define fun(pa) #@pa
char a=fun(a); //被展开为char a='a';
3. ##:参数连接操作,即将宏定义的多个形参连接成一个实际参数,如:
#define COMMAND(a,b) a##b
...
COMMAND(1,2); //相当于12
CMOOAND(ac,b); //相当于acb
4. \:当前行继续操作,实际上是对换行符转义,如:
#define LOOP(FROM, TO, CONTENT)\
for(int i=FROM;i<TO;i++){\
CONTENT\
}
5. _VA_ARGS_:变长参数操作,即可以接受不定个数的参数,如:
#define eprintf(...) fprintf (stderr, __VA_ARGS__)
eprintf ("%s:%d: ", input_file, lineno)
//==> fprintf (stderr, "%s:%d: ", input_file, lineno)
为什么要使用宏定义
简而言之,使用宏定义可以提高代码的可读性
具体的说,可以减少magic number的使用,并且可以做一些方便的替换,如下面的代码:
#define MALLOC(n, type) (type*)malloc((n)*sizeof(type))
使用时,int *p=MALLOC(10, int);
即可
宏的规范写法
1. 宏名大写
2. 宏定义语句末尾不加分号
3. 宏函数的形式参数不加类型
另外宏定义需要注意的
1. 宏定义可以嵌套
2. 宏定义不能出现在字符串的“”中
3. 宏定义不分配内存,变量定义才分配内存
4. 宏定义只是简单的替换,而且是直接对源码的字符串替换,如下面的宏定义就不能很好的表达求平方函数:
#define sqrt(x) x*x
...
int y=sqrt(1+2); //y = 1+2*1+2 = 5 ≠9
这时候加上括号就好了:
#define sqrt(x) (x)*(x)
...
int y=sqrt(1+2); //y = (1+2)*(1+2) = 9
5. 宏函数和自定义函数相比,效率更高但是安全性低且会使编译生成的目标文件变大;宏函数没有分配和释放栈帧、传参、传返回值等一系列工作,适合那些简短并且频繁调用的函数,但是对于递归则不推荐使用宏
https://blog.csdn.net/abc_12366/article/details/79155540
C语言的头文件和宏定义详解相关推荐
- 转 C++宏定义详解
来自:传送门 C++宏定义详解 一.#define的基本用法 #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往 ...
- 【C++】C++中的头文件(.h)—详解(2)
接上... [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 头文件中写些什么 在上篇博客中写到头文件本身不参与编译,但是它们被包含到源文件中 ...
- 【C++】C++中的头文件(.h)—详解(1)
[fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 前言 之前写过一篇<C++中头文件的使用>,那篇文章主要讲述C++中头文件的使用 ...
- C++中的宏定义详解
转载自:C++中的宏定义 和 C++宏定义详解 目录 一.#define解析 1 #define命令剖析 1.1 #define的概念 1.2 宏替换发生的时机 1.3 ANSI标准说明了五个预定 ...
- c语言寄存器头文件共用重复定义,C语言头文件的使用
让我们的思绪乘着时间机器回到大学一年级.C原来老师正在讲台上讲着我们的第一个C语言程序: Hello world! 文件名 First.c main() { printf("Hello wo ...
- c语言binsearch函数头文件,C++ binary_search()函数详解
binary_search()函数定义在头文件中,用于查找指定区域内是否包含某个目标元素. 该函数有 2 种语法格式,分别为: //查找 [first, last) 区域内是否包含 val bool ...
- android常用头文件,Android.mk 使用详解
和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点:一.Android.mk 简介二.Android.mk 的基本格式三.Android.mk 深入学习一四. ...
- linux 内核 THIS_MODULE宏定义详解
结构体struct module在内核中代表一个内核模块,通过insmod(实际执行init_module系统调用)把自己编写的内核模块插入内核时,模块便与一个 struct module结构体相关联 ...
- Linux中THIS_MODULE宏定义详解
一直都在耿耿于怀,这个THIS_MODULE到底是个什么玩意,linux内核中无处不在的东西.今天上网搜了一下,算是基本明白了.网上牛人写的已经比较详细,另外目前暂时没有时间往更深层次分析,所以直接贴 ...
最新文章
- spacemacs各种问题修复方法
- React学习笔记1:React基本概念
- python自动测试p-Python实践60-性能调优之pstats模块
- Java中数组以及集合
- 用Python求出:1到某个数的奇数序列里一共出现了多少个3
- Java进阶:图文并茂解析HashMap源码
- spring--aop总结
- 【性能优化】 之 并行执行
- 人口预测和阻尼-增长模型_使用分类模型预测利率-第2部分
- JIT编译器,内联和转义分析
- Java中的JsonConfig详解
- 【OpenCV】图像的内存分配与释放以及复制图像
- vb计算机教程,《计算机级VB教程》PPT课件.ppt
- 深入浅出Python的抽象基类
- Slf4j+logback实现日志打印-获取调用者类及方法行数信息
- 不要在循环中访问数据库,这样会严重影响数据库性能
- 物理学的困惑: 弦理论崛起了, 科学却衰落了
- Nesssus Pro 8.13.1下载安装
- 类似酷我音乐盒设计小总结(C#版)
- sql server高级查询及更新操作二
热门文章
- 计算机李维,李维-计算机科学学院
- 计算机自带的超级锁怎么设置,MIUI自带机密解锁+超顺畅设置小窍门
- Pyinstaller打包的exe文件过大的解决方法
- exe闪退 怎样解决python_python文件打开闪退要怎么处理?
- 155句经典语,太有才了.
- godspeed机器人_如何评价油管老高与小茉(原kuaizero老高频道)?
- 老鱼Python数据分析——篇七:将爬取的数据保存到CSV文件
- C#:实现24点游戏算法(附完整源码)
- AI 工具分享第 4 期:13 款国外免费AI视频生成工具
- 程序员因薪资低拒绝offer,HR恼羞成怒,网友瞬间炸翻了..