C语言作用域和链接属性

一.作用域

当变量被定义在程序不同位置时,它的作用范围是不一样的,这个作用范围就是我们所说的作用域。

C语言编译器可以确认4种不同类型的作用域:

——代码块作用域

——文件作用域

——原型作用域

——函数作用域

1.代码块作用域

在代码块中定义的变量,具有代码块作用域。作用范围是从变量定义的位置开始,到标志该代码块结束的右大括号{}处

尽管函数的形式参数不在大括号内定义,但同样具有代码块作用域,隶属于包含函数体的代码块

#include <stdio.h>

int main(void)
{
    int i = 100; // i1
    {
        int i = 110; // i2
        {
            int i = 120; // i3
            printf("i = %d\n", i);
        }
        // i = 110
        {
            printf("i = %d\n", i);
            int i = 130; // i4
            printf("i = %d\n", i);
        }
        printf("i = %d\n", i);
    }
    printf("i = %d\n", i);

    return 0;
}

 

 

2.文件作用域

任何在代码块之外声明的标识符都具有文件作用域,作用范围是从它们的声明位置开始,到文件的结尾处都是可以访问的。

另外,函数名也具有文件作用域,因为函数名本身也是在代码块之外。

#include <stdio.h>

void func(void);

int main(void)
{
    extern int count;

    func();
    count++;
    printf("In main, count = %d\n", count);    

    return 0;
}

int count;

void func(void)
{
    count++;
    printf("In func, count = %d\n", count);
}

 

3.原型作用域

原型作用域只适用于那些在函数原型中声明的参数名。函数在声明的时候可以不写参数的名字(但参数类型是必须是写上的),其实函数原型的参数名还可以随便写一个名字,不必与形式参数相匹配。

void func(int a,int b,int c);
void func(int d,int e, int f)
{
....
}

4.函数作用域

函数作用域只适用于goto语句的标签,作用将goto语句的标签限制在同一个函数内部,以及防止出现重名标签

二.定义和声明

当一个变量被定义的时候,编译器为变量申请内存空间并填充一些值。
当一个变量被声明的时候,编译器就知道该变量被定义在其他地方。
声明是通知编译器该变量名及相关的类型已存在,不需要再为此申请内存空间。
局部变量既是定义又是声明。
定义只能来一次,否则就叫做重复定义某个同名变量;而声明可以有很多次。

三.链接属性

1.external(外部的)
多个文件中声明的同名标识符表示同一个实体
internal(内部的)
单个文件中声明的同名标识符表示同一个实体
none(无)
声明的同名标识符被当作独立不同的实体

2.只有具备文件作用域的标识符才能拥有external或internal的链接属性,其他作用域的标识符都是none属性。
默认情况下,具备文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。
 
3.使用static关键字可以使得原先拥有external属性的标识符变为internal属性。这里有两点需要注意:
使用static关键字修改链接属性,只对具有文件作用域的标识符生效(对于拥有其他作用域的标识符是另一种功能)
链接属性只能修改一次,也就是说一旦将标识符的链接属性变为internal,就无法变回external了
 

 

 编译器工作原理:https://fishc.com.cn/forum.php?mod=viewthread&tid=78063&extra=page%3D1%26filter%3Dtypeid%26typeid%3D571

 

 

posted @ 2019-09-27 15:10  清歌牧言  阅读(1573)  评论(0编辑  收藏  举报