必看的C语言教程之头文件那点事

本文详细介绍了C语言中的编译预处理命令,包括#define定义宏、多行宏、预定义宏等。接着讲解了多个源文件的编译和链接过程,以及头文件在确保函数对接成功中的作用。头文件的#include机制、查找路径和标准头文件结构也进行了说明。此外,文章还提到了静态函数和全局变量的限制以及声明的作用。
摘要由CSDN通过智能技术生成

🍊博客主页:Geekwyz的江湖背景
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
🌟本文由 Geekwyz原创
🙏作者水平很有限,如果发现错误,欢迎留言


1.编译预处理命令

  • #号开头的是编译预处理命令
  • #define 用来定义一个宏

比如我们现在要定义一个常量
我们可以使用#define的形式,例如定义PI为3.14159

#include<stdio.h>
#define PI 3.14159

int main(){
    int r = 2;
    printf("%lf\n",2 * r * PI);//输出周长
    printf("%lf",r * r * PI);//输出面积
    return 0;
}

在开始编译之前会把所有的PI全部替换为3.14159

  • 定义多行的宏
#include<stdio.h>

#define a printf("Hello,world!\n");\
          printf("Hello,world1");
int main(){
    a;
    return 0;
}
  • 我们也可以定义没有值的宏,
    这类宏是用于条件编译的,如果有则编译,如果没有则不编译
  • C语言中也有一些预定义的宏
    – 比如_LINE_,_FILE__DATA_,_TIME__STOC_
    ---------行号----文件名----编译时的日期-----
  • 带参数的宏
#include<stdio.h>

#define cube(x)((x * x * x))
int main(){
    printf("%d",cube(4));//64
    return 0;
}

【错误写法】

  • #define RADTODEG(x)(x * 3.14159)
  • #define RADTODEG(x) (x) * 3.14159
    因为它会整体替换,假如x写成3 + 2那么表达式就会变成,3 + 2 * 3.14159发生错误,
  • 改进写法#define RADTODEG(x)((x) * 3.14159 )
    只要记住要参数的地方都要用到括号
  • 宏可以有多个参数
    #define min(x,y)((x) > (y)?(x) : (y))

2.多个源文件

  • 在devc++中新建一个项目,然后把几个源代码文件添加进去
  • 对于项目,devc++的编译器会把一个项目中所有源代码文件都编译后,链接起来
  • 有的IDE有分开的编译和构建两个按钮,前者是对单个源代码文件进行编译,后者是对整个项目做链接
    在这里插入图片描述
#include<stdio.h>
int max(int a,int b);
int main(){
    int a = max(1,2);
    return 0;
}
int max(int a,int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

3.头文件

如果没有int max(int a,int b);的声明,那么编译器会自动去猜,如果max函数的返回值或形参列表和传入的数据不同,那么就会发生错误,我的理解就是对接失败了
那如何才能让这两个对接成功呢?,这个时候就需要我们的头文件了。头文件就可以使这两者对接成功
在这里插入图片描述
在这里插入图片描述

我们把一个函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源文件(.c文件)中#include这个头文件,就能让编译器在编译的时候知道函数的原型,头文件就是一个合同,合同是双方的,一方是对max.c,一方是对hello.c

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

int main(){
	double a = max(1,2);
	printf("%lf",a);
	return 0;
}
#include "max.h"

double max(double a,double b){
	if (a >= b){
		return a;
	} else {
		return b;
	}
}
double max(double a,double b); //头文件

include命令在编译前就已经处理了,把那个文件的全部内容原封不动的插入到它所在的地方

  • " "双引号表示在当前目录下去找
  • <>让编译器在指定的目录中找,编译器自已知道自已的标准库的头文件在哪
  • 环境变量和编译器命令行参数也可以指定寻找头文件的目录
  • #include不是用来引入库的
    stdio.h里面只用printf的原型,printf的代码在另外的地方,某个.lib.a中·
    #include<stdio.h>只是让编译器知道printf函数的原型,保证你给给的参数为正确类型

使用建议

  • 在使用和定义这个函数的地方都应该#include这个头文件
  • 一般的做法就是任何.c都有对应的同名的.h,把所有对外公开的函数的原型和全局变量的声明全放进去,全局变量也可以在多个.c文件中共享

4.不对外公开的函数

  • 当我们在函数的前面加上static,这个函数只能在所在的编译单元中使用
  • 当我们在全局变量前面添加static就使得,这个全局变量,只能在所在的编译单元中使用

5.声明

上面我们展示了外部函数的使用。现在我们来说一下外部全局变量的使用
当我们在使用外部的全局变量的时候,我们需要在刚才的头文件中添加extern 全局变量的类型 标识符然后在去定义全局变量,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 一些规则

头文件中放声明

  • 声明是不会产生代码的东西

函数原型,变量声明,结构声明,宏声明,枚举声明,类型声明,inline函数

5.标准头文件结构

这里的结构指的就是结构体

  • 同一个编译单元中,相同的结构不能被重复声明,就是在main函数中重复编译了两次,相当于结构体重名
  • 所以这时候我们就需要标准头文件结构
#ifndef _LIST_ HEAD_//防止重名
#define _LIST_HEAD_

typedef struct _list{

}
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值