1 多文件编译不使用#include头文件的方式
(1)两次出现int val
#include<stdio.h>
int val;
int val; //第二次出现 int val,则表示声明
int main(){
return 0;
}
为了防止出现上述问题,全局变量在声明(是声明,不是定义)的时候,一律加上extern进行修饰,即external int val;
(2)extern与static总结
声明其他文件中的全局变量,不加extern也是可以的,当然,这只是不推荐而已,但工作中经常要看别人写的程序,如果别人没有加extern时,则需要明白下面的规则:
a.首先,同时在两个文件中出现全局变量int val;
是可以的,这里会被编译器当成是一个定义,另一个声明;
b.但却不能同时出现int var=10
,因为这两个都是定义,有初始化了,当然,只在其中一个文件中出现全局变量int var=10
,另一个文件中出现全局变量int val;
是可以的(一个被当成定义,另一个被当成声明);
c.如果某个文件(file1.c)中出现int var=10
,另一个文件(file2.c)虽然不能出现int var=100
,但却可以出现static int var=100
,对于这个文件(file2.c),使用var时为就近原则,即使用静态全局变量,并且这里的val只能在本文件中使用。
总结:声明其他文件中的全局变量最好使用extern,这样可以减少歧义;如果全局变量添加了static,则是静态局部变量,只能在本文件使用。
(3)声明其他文件中的函数
file1.c内容
int a = 10;
void func1() {
printf("func1\n");
}
static void func2() {
printf("func2\n");
}
file2.c内容
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int a; //如果声明在函数外面,则不需要加上extern,但建议加上
void test01()
{
//int a; //这里会被当成定义局部变量
//extern int a; //如果声明在函数里面,则必须加上extern
printf("a = %d\n", a);
}
//void func1(); //函数的声明写在外部
void test02()
{
void func1(); //函数的声明既可以放在函数的内部,也可以放在外部,可以不用加extern
func1(); //也可以不用声明,直接使用,但是这样会发生警告
}
//func3()无论是否声明,无论是否加extern,无论声明在函数内部还是外部,都无法编译通过
//void test03()
//{
// extern void func3();
// func3();
//}
int main() {
test02();
return EXIT_SUCCESS;
}
总结:分文件编程时:
(1)变量必须声明,最好使用extern,可以减少歧义,增加可读性;
(2)函数可以不声明直接用,但会有警告;如果确实想声明,那么声明时无需extern,可以在函数内部声明,也可以在函数外面;
(3)使用static声明的函数,只能在所在文件中使用,无法跨文件。
2 多文件编译使用#include头文件的方式
新建一个头文件,名为file1.h
#pragma once
extern int a; //最好在这里加extern,因为主文件中会使用#include头文件的方式,
//#include指令在预处理阶段执行,使得file1.h和主文件本质上是一个文件
void func1();
新建一个名为file1.c的文件,内容如下:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int a = 10;
void func1() {
printf("func1\n");
}
static void func2() {
printf("func2\n");
}
再建一个名为file2.c的文件,内容如下:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "file1.h" //有了这句话,等价于声明
int main() {
printf("a = %d\n", a);
func1();
return EXIT_SUCCESS;
}
输出
a = 10
func1
#include
指令在预处理阶段执行,使得file1.h和主文件(file2.c)本质上是一个文件。
通过头文件分文件编译,就可以不需要声明了,当然,在头文件中声明变量时,尽量还要加extern。
多文件编译尽量使用#include头文件的方式。