在C程序中,当同一个变量或函数出现在多个地方或者同一个变量或函数存在于多个源文件中的时候,他们是表示同一个实体呢还是表示不同实体?且看下面详细讲解:
* 先简要介绍C语言的几种作用域 *
作用域:
可以归纳为下面几种作用域:
-
代码块作用域
以一对闭合花括号( { } )包围的代码称为代码块,代码块中还可以嵌套代码块。所以嵌套越深的代码块中定义的变量会覆盖掉较浅代码块中定义的变量;举例如下:
#include <stdio.h>
int a=10; //全局变量
void fun(){
printf("%d\n",a);
int a=20;
{
int a=30;
printf("%d\n",a);
}
printf("%d\n",a);
}
int main(){
fun();
return 0;
}
输出结果:
10
30
20
- 文件作用域
在所有的代码块中声明的变量或者函数都有文件作用域,从声明处到文件结尾处都可以访问该声明。
另外通过#include
这样的预编译指令包含其他文件,就好像被包含文件是直接写在该文件中的一样,所以他的作用域并不局限于头文件中,而在包含它的文件中依旧可以访问到。
- 原型作用域
在声明函数的时候,我们并不需要给定参数名,只需要表明参数类型就可以了。所以如下声明中的 a 和 b 可有可无,在后面调用该函数的时候传递的参数名不需要与定义时的参数名一致。其实,在这里唯一需要注意的是,同一个函数的声明中,不同的参数不可以使用同一个名字。即不可为void fun(int a,int a)
。
void fun(int a,int b);
- 函数作用域
这个很好理解,它是针对goto
关键字来说的,在一个函数的不可以使用相同的语句标签。
* 至此单个文件的问题算是解决了 *
* 下面且看多个文件,但在此前需要提提链接属性 *
链接属性
首先需要提出三种链接属性,每个变量或函数都有自己的链接属性,不同的链接属性决定了如何处理在不同文件中出现的相同声明。
- 外部链接(external)
外部链接属性说明无论在多少个文件声明多少次,位于不同源文件中的变量或函数都指的是同一个实体。
- 内部链接(internal)
内部链接表示在同一个源文件中的声明是指向同一实体,但位于不同源文件的多个声明属于
不同的实体。
- 无(none)
没有链接属性指,多个声明分别表示不同的实体。
下面举例说明,三种属性的得来方式:
typedef char *ptrToChar
int a;
int b(int c){
int d;
int e(int f);
}
static int g;
外部链接:全局变量,以及函数的链接属性为外部链接,即以上代码中的 a ,b,e 的链接属性为外部链接。
内部链接 :使用
static
修饰正常情况下为外部链接的变量可以是其链接属性变为内部链接,即 g 。无 : 而代码块中定于的变量的链接属性为无( none ),除去外部链接与内部链接,其余的链接属性皆为无。
而这些属性有说明什么呢?这里需要引出两个关键字。
extern
有时候我们希望使用其他源文件中定义的变量或者函数。
比如下面的两个源文件,hello.c 中定义了一个字符串,而在print.c中需要打印这个字符串:
/*hello.c*/
char *a = "hello,world!\n";
/*print.c*/
#include <stdio.h>
char *a;
int main(){
printf("%s",a);
return 0;
}
使用命令行gcc hello.c print.c
编译后打印出hello,world!
。在这里 a 具有外部链接属性,所以在print.c
中声明的 a 实际上与 hello.c
中的 a 是同一个实体。
但是有时候为了表明 a 是在其他源文件中定义的我们在其前面加上 extern
。但要明白不加该关键字也可以。为了程序的易读性建议加上。故修改如下:
/*print.c*/
#include <stdio.h>
extern char *a;
int main(){
printf("%s",a);
return 0;
}
static
static 关键字使链接属性变为 内部链接,如下
static int b;
- 在其他文件中遇到 b 则是指其他的变量 b 。
static void fun();
- 而在函数前面加上
static
则指明该函数只能在该文件中被调用。
void count(){
static int num=0;
num++;
}
- 在代码块中声明的变量前加
static
。要注意这里若不加static
那么num的链接属性是 无( none ) 。这实际上等同于声明一个全局变量,特殊的是该全局变量只能被该函数使用。
总结
在单个文件中使用变量的时候要牢牢记住优先级。
面对多个文件要理解关键字 static 与 extern 。这两个关键字只是使用在声明变量的时候。
extern 用于指明该变量为外部链接,实际上可以有可无,但加上便于阅读。
static 有三种用法:
- 用在全局变量前,表示该变量的属性为内部链接,即只能在该文件中调用。
- 用在函数前,表示该函数只能在该文件中被调用。
- 用在函数的代码块中,这实际上是声明了一个全局变量,但是这个全局变量只能被该函数使用。