当前位置 博文首页 > jtwqwq的博客:翁恺老师C语言程序设计网课(13)

    jtwqwq的博客:翁恺老师C语言程序设计网课(13)

    作者:[db:作者] 时间:2021-08-19 09:51

    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也能起到相同的作用,但是并不是所有的编译器都支持。所以还是用标准头文件结构。

    cs