C语言标识符作用域、外部对象连接属性和变量的储存属性

标识符作用域

1. 标识符(identifier)用于代表程序中的对象,根据所代表的对象不同,可将标识符分为变量名、数组名、函数名、数据类型说明符、符号常量名(宏名)和语句标号。

2. 标识符的作用域:

  • 文件作用域:指从标识符定义或声明位置起到源文件结尾的源文件范围。外部对象(全局变量名、全局数组名、函数名、在函数外自定义的数据类型名)都具有文件作用域,其作用域可以通过引用性声明扩大。全局变量的"定义"与全局变量的"声明"是不相同的,全局变量的定义只能有一次, 它的位置是在所有函数之外,而同一个文件中的全局变量声明可以是多次的,它可以在函数之内(哪个函数要用就在那个函数中声明)也可以在函数之外(在全局变量的定义点之前)。系统会根据全局变量的定义(而不是全局外部变量的声明)分配存储空间的。对于全局变量来讲,初始化只能是在"定义"中进行,而不是在" 声明"中
#include<stdio.h>
int x;//变量x的引用性声明,不需要建立存储空间

void main()
{
    printf("%d",x);
}

int x=1;//外部变量x的定义,需要建立存储空间
  • 函数作用域:指一个函数定义所覆盖的区域。
  • 块作用域:指一个函数体内一个代码块(一条复合语句)的范围。块作用域总是嵌入在函数作用域内,一个块作用域还可以包含多个块作用域。
  • 函数原型作用域:指引用函数的函数原型说明中使用的参数名的作用域。

3. 标识符作用域规则

  ①不允许同一作用域内定义或声明代表不同对象的同名标识符。

  ②允许不同作用域内定义或声明代表不同对象的同名标识符。

  ③内层作用域中访问的同名标识符是内层作用域中定义的标识符,此时外层作用域中定义的同名标识符被自动隐蔽不可访问。以下程序输出结果:2 2 2 2 5 0。

 1 #include<stdio.h>
 2 int x=0;
 3 void f();
 4 
 5 int main()
 6  {
 7     int x;
 8     for(x=1;x<5;x++){
 9        int x=2;
10        printf("%d",x);
11     }
12     printf("%d",x);
13     f();
14     return 0;
15 }
16 
17 void f()
18 {
19     printf("%d",x++);
20 }

外部对象连接属性

1. 同一个代码段中的函数名只允许在一个源文件中被定义一次,允许在多个源文件中被多次地引用性声明。

2. 它们具有两种连接属性之一:内部连接(internal linkage)和外部连接(external linkage)。分别对应储存类型说明符 static和extern。

extern 返回值类型说明符 函数名(形参类型表); 
extern 数据类型说明符 全局变量名;

变量的储存属性

1. 变量的生存周期属性

  • 静态变量:生存周期与程序运行时间相同。
  • 动态变量:生存周期与定义它的代码块被执行的时间相同。函数的形参都是动态变量。
  • 局部变量有静态个动态之分。使用static声明的局部变量是静态的,使用auto或register声明的局部变量是动态的。
  • 静态局部变量的生存周期与全局变量相同,但作用域与局部变量相同。
  • 未指定初值时,静态局部变量和全局变量在编译时被初始化为0,动态局部变量的初值不确定。
//利用静态局部变量储存特性计算阶乘
long f(int n)
{
    static long s;
    if(n<=1)
        s=1;
    else
        s*=n;
        return s;
}
int main(void)
{
    int i;
    double k=0;
    for(i=1;i<=0;i++)
        k+=1.0/f(i);
    printf("%lf",k);
    return 0;
}

2. 变量的储存器属性

  • 静态变量在程序运行期间是始终存在的,全部是内存变量。
  • 动态变量可以放在内存中也可以放在寄存器中。
  • 寄存器没有地址,不能对register变量执行取地址操作。不能通过scanf函数对其赋值。
posted @ 2021-05-10 09:47  结城梨斗  阅读(390)  评论(0编辑  收藏  举报