C语言_13 文件

简介: 多个源代码文件

12.3.1 多个源代码文件

main中的代码太长,可以分出几个函数;而一个源代码文件(.c)太长可以分出很多.c文件。
如果我们直接把函数拿到另一个源代码文件里,编译很明显不会通过。我们需要新建一个项目。
新建-项目,选择console application终端应用,把它保存到和两个目标源代码文件同一个文件夹里。
新建之后会自带一个.c文件,这个是假的,删掉即可。然后项目-添加,添加两个目标源代码文件,这样就可以编译并运行了。
对于一个项目,Dev C++会把里面所有的文件编译并链接起来。
其实Dev C++是个比较特殊的(IDE)集成开发环境,绝大多数其他的IDE都需要你先建一个项目(哪怕只有一个源代码文件),然后才能进行其他操作。
比如有的IDE是有编译和构建两个按钮,前者对单个源代码文件进行编译,后者对所有源代码文件链接。因为一个源代码文件是一个编译单元,编译器每次只对一个编译单元进行编译(形成.o目标代码文件)。

12.3.2 头文件

在刚才的多个源代码文件中,我们在main文件里有加入一条声明:
int max(int a,int b);如果不加这条声明,其实C语言也会默认a和b是Int类型的。
可是如果a,b都是double,我们又不加声明呢?输出了一个奇怪的大数字。
main中默认a,b是int→传入double 的max→以int形式传回来,链接的确没有问题,但传入传出都是错的。
如何让他们一致?我们需要头文件。
1.再新建一个源代码文件,会提示要不要在项目中添加,点yes;
2.命名为.h的文件(如max.h)输入一句话,就是那句函数的原型
int max(int a,int b);
3.在所有调用这个函数的源代码文件:main.c和max.c文件中都加入该头文件

#include"max.h"

这下如果两边的max函数类型不一样,编译就会提示有问题了。

include是一个编译预处理指令,会把该头文件下的所有内容原封不动地插入他所在的地方;因此也不是必须在最开头。

注意到#include后面的括号有两种:
"":先去找系统内指定目录有没有这个头文件,没有再去当前目录找。
<>:只在系统内找这个头文件。
在这里插入图片描述
这样查看stdio.h里都有什么
关于#include的误区:#include不是用来引入库的。而是原封不动地把库里的东西插入到这一行来
stdio.h里只有printf的原型,其代码在另外的地方。比如windows在.lib里,unix在.a里。而stdlib.h里有malloc的原型
而现在的C语言编译器会默认引入所有标准库

include<stdio.h>只是为了让编译器知道printf函数的原型,保证调用时给出的参数值是正确的类型。

应该在使用、定义该函数的地方都包含该头文件,把所有对外公开的函数的原型和全局变量的声明都放进去。
全局变量也可以在多个源代码文件中共享;不过也像函数一样要有恰当的方法。
如果在函数前加static:只能在该源代码文件中使用
如果在全局变量前加static:只能在该编译单元中使用。

12.3.3 声明

上节课的问题:怎样让全局变量在多个.c文件中共享?
在.h中输入
extern int gAll;
int x;是变量的定义;extern int x;是变量的声明。
声明不产生代码(单纯地记住这句声明:这个项目中不管在哪里,有一个全局变量gAll);而定义产生代码。
只有声明才可以被放在头文件中。否则一个项目中多个编译单元里会有重名的实体。
重复声明:同一个头文件中,同名的结构不能被重复声明。如果头文件里有结构的声明,很难这个文件不会在一个编译单元里被#include多次。(比如我们在max.h里定义过该struct,然后在min.h里要用到这个结构就会#include"max.h";这样在主函数中就要#include"max.h" #include"min.h",就会重复声明,再次出现在.i中。尽管再怎么避免这件事的发生,在.h中加入了结构,还是很有可能会发生的。)
为了解决这种情况,我们需要在max.h和min.h开头加入标准头文件结构:

#ifndef __MAX_H__
#define __MAX_H__//如果没有定义过max.h则定义max.h


//中间是声明


#endif

这样,只要max.h被定义过了,在其他头文件就不会被重复#include了。

pragma once也能起到相同的作用,但是并不是所有的编译器都支持。所以还是用标准头文件结构。

目录
相关文章
|
29天前
|
存储 编译器 C语言
如何在 C 语言中判断文件缓冲区是否需要刷新?
在C语言中,可以通过检查文件流的内部状态或使用`fflush`函数尝试刷新缓冲区来判断文件缓冲区是否需要刷新。通常,当缓冲区满、遇到换行符或显式调用`fflush`时,缓冲区会自动刷新。
|
29天前
|
存储 编译器 C语言
C语言:文件缓冲区刷新方式有几种
C语言中文件缓冲区的刷新方式主要包括三种:自动刷新(如遇到换行符或缓冲区满)、显式调用 fflush() 函数强制刷新、以及关闭文件时自动刷新。这些方法确保数据及时写入文件。
|
1月前
|
C语言
【C语言】探索文件读写函数的全貌(三)
【C语言】探索文件读写函数的全貌
|
1月前
|
存储 C语言
【C语言】探索文件读写函数的全貌(二)
【C语言】探索文件读写函数的全貌
|
1月前
|
C语言
【C语言】探索文件读写函数的全貌(一)
【C语言】探索文件读写函数的全貌
|
1月前
|
存储 文件存储 C语言
【C语言】深入了解文件:简明指南
【C语言】深入了解文件:简明指南
|
2月前
|
Linux C语言
C语言 文件IO (系统调用)
本文介绍了Linux系统调用中的文件I/O操作,包括文件描述符、`open`、`read`、`write`、`lseek`、`close`、`dup`、`dup2`等函数,以及如何获取文件属性信息(`stat`)、用户信息(`getpwuid`)和组信息(`getgrgid`)。此外还介绍了目录操作函数如`opendir`、`readdir`、`rewinddir`和`closedir`,并提供了相关示例代码。系统调用直接与内核交互,没有缓冲机制,效率相对较低,但实时性更高。
|
3月前
|
存储 C语言
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
53 15
|
3月前
|
存储 C语言
【c语言】职工信息管理系统 包含读取写入txt文件,职工信息的增删改查
【c语言】职工信息管理系统 包含读取写入txt文件,职工信息的增删改查
|
3月前
|
存储 自然语言处理 程序员
【C语言】文件的编译链接和预处理
【C语言】文件的编译链接和预处理