C语言笔记16

88 阅读3分钟

存储类别

两个概念

  1. 生命期 数据对象从创建到销毁之间 数据对象存在的周期
  2. 作用域 标识符对数据对象指代关系存在的区域 是一种关联关系

自动变量auto

也被称为局部变量
默认情况下 声明在代码块内的任何变量都属于自动储存类别的变量

  • 生命期:从包含声明的代码块开始到包含声明的块结束
  • 作用域:从声明开始到包含声明的块结束
#include <stdio.h>
int *func()
{
    int n = 100;
    return &n;
}

int main()
{
    int *PN = func();//虽然返回了指针 但变量n的生命期已结束 指向的是已失效的空间 被称为野指针 访问野指针可能导致崩溃
    printf( "%d\n",*pN);
    return 0;
}

文件作用域的静态变量

声明在代码块外中的任何变量都属于静态存储类别的变量
与自动变量不同 若静态变量没有初始化 那么默认初始化为0

  • 生命期:在程序启动时创建 直到程序结束时才销毁
  • 作用域:从声明开始到包含声明文件结束
#include <stdio.h>
int n;
void func()
{
    printf("n = %d\n", n);//0
    func();
    func();
    func();
    printf("n = %d\n", n);//3
    return 0;
}    

变量n声明在代码块外 因此,它具有文件作用域 从声明开始 直到文件结束 标识符n均指代int n声明的数据对象 因此 函数func以及函数main中均可使用标识符n 并且它们指代同一个数据对象

块作用域的静态变量static

在代码块内 使用关键词static 指明变量n为静态储存类型
与自动变量不同 若静态变量没有初始化 那么默认初始化为0

  • 生命期:在程序启动时创建 直到程序结束时才销毁
  • 作用域:具有块作用域 从函数func中的变量声明开始到函数func结束
#include <stdio.h>

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

int main()
{
    func();//0
    func();//1
    func();//2
    return 0;
}

变量n具有块作用域 且函数main不在块作用域内 因此 无法在函数main中使用标识符n访问该数据对象 但是 可以用指针!

#include<stdio.h>

int* func()
{
	static int n;
	n++;
	return &n;
}

int main()
{
	int* pn = func();
	printf("n=%d\n", *pn);//n=1

	func();
	printf("n=%d\n", *pn);//n=2

	func();
	printf("n=%d\n", *pn);//n=3
	return 0;
}

外部链接的静态变量

文件作用域静态变量也被称作全局变量 多个源文件中 不允许出现同名全局变量 但可以共享一个全局变量
若变量在一个源文件中声明 那么在另一个源文件中 可以通过extern关键词 外部链接全局变量
04947ED46DCAD8611AF9C0D1F5811239.jpg

仅限本文件使用的全局变量

如果不想源文件中的全局变量被其他文件链接使用那么可以在变量的声明前加上关键词static
这里的static并不是声明它是一个静态变量的意思 而是拒绝与其他源文件共享本源文件中声明的变量
这样变量就仅限本文件使用 即使在别的源文件中声明了同名全局变量 也不会发生符号重定义
同时 别的源文件也无法通过extern链接到具有static的全局变量

源文件main.c  

#include <stdio.h>
#include "other.h"

static int n = 123;1//仅限main.c使用的变量n

int main()
{
    printf("n in main %d\n", n);//n in main 123
    other();//n in other 456
    return0;
}


源文件other.c

#include <stdio.h>
#include "other.h”

static int n = 456;//仅限other.c使用的变量

void other()
{
    printf("n in other %d\n", n);
}