作用域、可见性
一个变量标识符只有在特定的某段儿程序区域(作用域)内才可以起作用(可见性)。
总共有四种作用域:函数作用域、文件作用域、语句块作用域、函数原型作用域
函数作用域
跳转标签(就是goto的label)是仅有的函数作用域的标识符,使用时,会与goto配合出现。
它不会受其他语句块儿的干扰,只要是在所处的函数里,什么地方都可以起作用。
int main() {
int count = 3;
HELLO_LABEL:
puts("hello \n");
if(-- count > 0) {
goto HELLO_LABEL;
}
switch(count) {
case 1: count = 0; break;
case 0:
count = 3;
SWITCH_INNER_LABEL:
printf("inside switch! \n");
break;
default :break;
}
if(-- count > 0) {
goto SWITCH_INNER_LABEL;
}
}
SWITCH_INNER_LABEL尽管是在switch的语句块儿里定义的,但还是可以从外部访问到。
文件作用域
文件作用域,即从它声明开始到文件结束都是可见的。
在所有函数外定义的标识符称为全局标识符,比如全局变量、函数声明、头文件中的标识符、宏定义。
#include <stdio.h> // 头文件中的
#define macro 10 // 定义的宏变量
int global_variable = 10; // 全局变量
void fun(void); // 函数声明中的函数
int main() {
/* do something */
return 0;
}
void fun(void) {
/* do something */
return ;
}
语句块作用域
声明出现在一个语句块儿里、或是函数定义的形参列表中。
-
当标识符的作用域完全相同时,不允许出现相同的标识符名,而当标识符有不同作用域时允许标识符同名。
-
如果是作用域嵌套的情况下,如果内层和外层的作用域声明了同名的标识符,那么在外层作用域中声明的标识符对于该内层作用域时不可见的。
int main() {
int i = 0;
{
int i = 2; // 这里内部的i起作用,可见
printf(“i2 = %d”, i); // i的值为2
i += 2;
}
i ++; // 这里外部的i起作用,可见
printf(“i1 = %d”, i); // 1
}
函数原型作用域
就是在函数原型声明里的标签
int fun(int argc, char** argv);
比如这里的argc和argv???
标识符的存储类型
全局对象与函数
extern声明的对象,或者缺省(无extern或static修饰)的函数具有外部链接。
能够被extern修饰的函数或对象是全局的,只要提前声明,则该对象和函数可在所有文件内可见。
在test.c中
extern int a;
void test(void) {
a = 10;
}
在main.c中
#include <stdio.h>
extern void test(void)
int a; // 全局变量a的声明
int a = 10; // 全局变量a的初始化(声明+定义)
int main() {
extern int a;
/* 只不过在main函数的语句块儿内重新声明了一下a,
声明成了(与全局变量a同名的)只具有语句块儿作用域的局部对象,
正好将全局变量a覆盖掉了,
但是这句话写和没写一个样 */
printf("a = %d \n");
return 0;
}
静态对象与函数
在文件作用域中声明的对象或函数,并且由static修饰。
静态对象或函数只能在该文件的上下文中可见,不会与其他文件中的对象或函数冲突。
#include <stdio.h>
static int a = 10;
static void fun(void);
int main() {
return 0;
}
static void fun(void) {
/* do something */
return ;
}
局部对象
声明为函数形参或者在一个语句块儿作用域中(未用static或extern)声明的对象。
局部对象,只要离开了声明它的语句块儿,它就失去了可见性(生命周期结束)。
在古早的C语言中,会使用auto或register声明一个局部变量。但C语言更新迭代到现在,这两个关键字几乎被废弃了。auto会显式地告诉编译器该变量是局部变量,register会建议编译器最好让变量存储在寄存器里(当然C编译器也不一定听从建议~~)
6978

被折叠的 条评论
为什么被折叠?



