首页 > 编程知识 正文

c语言h文件和c文件都要编译,c语言中.h文件一般放什么内容

时间:2023-05-06 20:30:11 阅读:195478 作者:3473

  我们通常在完成一个程序时,往往习惯将程序写为多文件的,这样就能实现程序的模块化管理,以及分工开发合作。而一些全局变量,全局函数,结构体等就能使各模块联系在一起。

  在平常大家写代码的过程中,通常会使用文件包含来联系各代码文件,当然初学者也可能会直接写成多文件程序,没有文件包含,这样也能编译、运行。

  在这里,写了一些小段的测试代码,来说明:包含.c文件,,直接多文件,包含.h文件三种方式的区别与应用。

1.包含.c文件

  可能有人不习惯写.h文件,而直接将代码写在.c文件中,其他文件要调用函数则直接包含.c文件。正如下面一段代码:

//fun.cint h = 0;int cal(int a, int b){ return (2*a+3*b);}//main.c#include "stdio.h"#include "fun.c" //包含.c文件int main(void){ h = 1; //直接使用fun.c中的变量 int i = 1,j = 2; int c = 0; c = cal(i, j); //直接调用fun.c中的函数 printf("%dn", c); return 0;}

        编译:gcc main.c -o main     直接编译通过,运行正确。

我们再看一个测试程序:

//fun.cint h = 0;int cal(int a, int b){ return (2*a+3*b);}//fun1.c#include "fun.c" // 就这一句//main.c#include "stdio.h"#include "fun.c" //包含.c文件#include "fun1.c" //添加包含fun1.cint main(void){ h = 1; //直接使用fun.c中的变量 int i = 1,j = 2; int c = 0; c = cal(i, j); //直接调用fun.c中的函数 printf("%dn", c); return 0;}

       编译:gcc main.c -o main   编译报错:h  cal  发生了重定义。

总结:

        优点:可以直接编译main.c文件,不用编译fun.c,因为在main.c的编译预处理阶段,会将fun.c 的代码直接拷贝过来。读者可以使用gcc -E main.c -o main.i  查看预处理后.i文件的代码。发现main.i中将fun.c的代码拷贝了过来。

   缺点:fun.c不能被多个文件包含,因为这样就会产生变量和函数的多个拷贝,造成严重的重定义,编译通不过。

        这种方式可解决较简单程序的文件包含问题,通常不推荐使用。

2.直接多文件

       多文件程序中,全局变量可以被外部引用,函数也默认是全局函数,可以被外部使用。废话少说,先上代码:

//fun.cint global_var = 0;int cal(int a, int b){ return (2*a+3*b);}//main.c#include "stdio.h"extern int global_var; // 声明外部变量int main(void){ global_var =1; //外部变量赋值 int i = 1,j = 2; int c = 0; c = cal(i, j); //外部函数调用 printf("%dn", c); return 0;}

Makefile书写为:

CFLAG=-Wall -O -g

main:main.o fun.o
gcc $(CFLAG) main.o fun.o -o main
main.o:main.c
gcc $(CFLAG) -c main.c -o main.o
fun.o:fun.c
gcc $(CFLAG) -c fun.c -o fun.o
clean:
rm main.o fun.o main

编译通过,会出现警告信息,说cal为隐含的外部函数。运行正确。结果还算理想,那么我们再来看一段:

1 int global_var = 0; 2 struct student 3 { 4 int age; 5 int num; 6 }; //定义结构体 7 struct student wang; //定义结构体变量 8 int cal(int a, int b) 9 {10 return (2*a+3*b);11 }12 13 #include "stdio.h"14 extern int global_var;15 extern struct student wang; //声明外部结构体变量16 int main(void)17 {18 wang.age = 10; //报错19 student li; //想使用外部的定义的结构体来定义一个变量 报错20 global_var =1;21 int i = 1,j = 2;22 int c = 0;23 c = cal(i, j);24 printf("%dn", c);25 return 0;26 }

同样的编译,main.c文件的编译会出现错误,首先是想使用外部定义的结构体变量(已作声明),报错。然后,想用外部结构体定义一个变量,报错。

总结:

  优点:不会出现重定义问题

  缺点:1、如果要用到的外部变量多,或是在多处要使用外部变量,则要在每一个调用的文件中使用extern声明,比较麻烦。

       2、如果是在fun.c中有结构体定义或是类的定义,在main.c中用使用结构体定义变量,或是使用类定义对象。编译不能通过,不知该如何处理。

       3、如果是定义在fun.c中的结构体变量,在main.c中要声明外部变量,并使用,会出错。故推知:结构体不能声明为外部变量,只能是包含的头文件中定义的结构体。

解决上述问题的方式就是第三种,包含.h文件方式。

3.包含.h文件

  为每一个模块都编写一个.c文件,一个.h文件。

  .c源文件中放:函数的定义,全局变量的定义,全局结构体变量的定义。

  .h头文件中放:函数的声明,全局变量的声明(extern),全局结构体的定义,全局结构体变量的声明。

  调用文件(main.c)文件中:包含.h头文件即可。不用声明任何东西。

  测试代码如下:

//fun.c#include "fun.h"int global_var = 0;struct student wang; //结构体变量定义int cal(int a, int b){ return (2*a+3*b);}//fun.h#ifndef _fun_h_ //条件编译,解决文件重复包含所引起的重定义问题#define _fun_h_struct student{ int age; int num;};extern int global_var;extern struct student wang;#endif//fun1.c#include "fun1.h" //没有实际代码//fun1.h#include "fun.h" //包含fun.h//main.c#include "stdio.h"#include "fun.h"#include "fun1.h"//extern int global_var;//extern struct student wang;int main(void){ wang.age = 10; //调用全局结构体变量 struct student li; //定义变量 global_var =1; //使用全局变量 int i = 1,j = 2; int c = 0; c = cal(i, j); printf("%dn", c); return 0;}

 总结:

    优点:解决了文件重复包含造成的重定义问题;函数,全局变量,结构体,结构体变量都能在外部调用;每一处调用变量的文件处不用重复的写声明语句,因为声明语句直接写在了.h头文件中,直接包含头文件即可。

 

转载于:https://www.cnblogs.com/goaheadnohesitate/p/3287807.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。