编译上下文

作用域、可见性

一个变量标识符只有在特定的某段儿程序区域(作用域)内才可以起作用(可见性)。

总共有四种作用域:函数作用域、文件作用域、语句块作用域、函数原型作用域

函数作用域

跳转标签(就是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);

比如这里的argcargv???

标识符的存储类型

全局对象与函数

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编译器也不一定听从建议~~)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值