C语言基础篇4:变量与存储

1 局部变量和全局变量

在介绍局部变量和全局变量前,先,了解一些关于作用域方面的内容。作用域的作用就是决定程序中的哪些语句是可用的,换句话说,就是程序中的可见性。作用域有局部作用域和全局作用域,那么局部变量就具有局部作用域,而全局变量就具有全局作用域。

1.1 局部变量

在一个函数的内部定义的变量就是局部变量,无法被别的函数使用。函数的形参也属于局部变量,作用范围仅限于函数内部的语句块。

【示例1.1】局部变量的作用域

cpp 复制代码
#include <stdio.h>
int main(){
    int i = 1;
    if(i > 0){
        int j = 2;
        if(j > 0){
            int m = 3;
            printf("all number %d %d %d \n",i,j,m);
        }
    }
    return 0;
}

在C语言中位于不同作用域的变量可以使用相同的标识符,也就是在这种情况下,变量名可以相同。如果在一个函数中,内层作用域中定义的变量和已经声明过的某个外层变量有相同的名字,那么内层作用域中的变量将覆盖外层作用域中的那个变量。

1.2 全局变量

程序的编译单位是源文件,上面说到,在函数中定义的变量称为局部变量。如果一个变量在所有的函数的外部声明,这个变量就是全局变量。全局变量是可以在程序中的任何位置进行访问的变量。

【注意】全局变量不属于某个函数,而是整个源文件。但如果外部文件要进行调用,需要使用extern进行引用修饰。

定义全局变量的作用是增加了函数间数据联系的渠道。由于同一个文件中的所有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值,就会影响到其他函数。

【示例1.2】使用全局变量

cpp 复制代码
#include <stdio.h>
int global = 100; //定义全局变量
void Store1Price();
void Store2Price();
void Store3Price();
void ChangePrice();
int main(){
    printf("调整之前,全局变量的值是: %d \n",global);
    Store1Price();
    Store2Price();
    Store3Price();
    ChangePrice();//修改全局变量的值
    printf("调整之后,全局变量的值是: %d \n",global);
    Store1Price();
    Store2Price();
    Store3Price();
}
void Store1Price(){
    printf("全局变量的值是:%d \n",global);
}
void Store2Price(){
    printf("全局变量的值是:%d \n",global);
}
void Store3Price(){
    printf("全局变量的值是:%d \n",global);
}
void ChangePrice(){
    printf("是否需要改变全局变量的值,希望改成:");
    scanf("%d",&global);
}

2 变量的存储类别

变量的存储类别决定变量什么时候被分配到指定的内存空间中,以及在什么时候释放内存空间。因此,存储类别就是为变量分配使用内存空间的方式,也可以称为存储方式。变量的存储类别分为两种形式,动态存储和静态存储。并且可以通过存储类修改符来告诉编译器要处理什么样的类型变量。具体有自动(auto)、静态(static)、寄存器(register)和外部(extern)4种。

2.1 静态存储和动态存储

从变量的产生时间上可以分为静态存储和动态存储。

静态存储就是指在程序运行时分配的固定的存储方式,而动态存储则是在程序运行期间根据需要进行动态的分配存储空间。

要理解动态存储和静态存储方式,首先要了解内存中用户存储空间的基本情况。系统提供用户的存储空间可以分为3个部分:程序区、静态存储区和动态存储区。

其中,程序区用来存放用户要执行的程序段。数据分别放在静态存储区和动态存储区中。

静态存储的变量位于内存的静态存储区,全局变量都保存在静态存储区中,因此全局变量从程序执行时开发分配存储单元,直到程序运行结束,才释放其所占的存储单元。

在动态存储区中存储跟堆栈操作相关的数据有关,堆栈中的数据随着进栈出栈操作而变化,当变量被弹出堆栈以后,其生存周期也就结束了。在调用函数时,其局部变量也被保存到动态存储区中,当函数结束执行,返回到主调函数时,变量所占用的空间将被释放,此时局部变量也将消失。由此可见,如果一个函数被调用了两次,其中变量的存储空间可能为不同的地址。

个存储区所存放的数据内容如下:

1、静态存储区:存储全局变量,在程序执行过程中,全局变量占据固定的内存空间,直到程序执行完毕才释放内存。

2、动态存储区:

1)自动变量,在函数调用时分配存储空间,调用完成释放存储空间。

2)函数调用时现场保护和返回地址,在函数被调用时分配内存空间。

3)函数形参:只有在调用该函数时才能为形参分配内存空间,调用完以后会将所有的空间释放掉。

从上述分析可知,静态存储变量是一直都存在的,而动态存储变量则是根据函数执行过程决定是否存在还是消失。

2.2 auto变量

该存储类型是C语言中使用最广泛的一种类型。C语音规定,函数内凡未加存储类型说明的变量,默认都是自动变量,也就是说自动变量可以省去说明符auto。

自动变量有以下特点:

1、自动变量的作用域仅限于定义该变量的个体内。在函数中定义的自动变量,只在该函数中有效。在复合语句中定义的自动变量只在该复合语句中有效。

2、自动变量属于动态存储方式,只有在使用它时,即定义该变量的函数被调用时才给它分配存储单元,函数调用结束,释放存储单元。因此函数调用结束后,自动变量的值不能保留。同样在复合语句中定义的自动变量,在退出复合语句后也不能在使用。

2.3 static变量

在编写程序的过程中,有些函数的局部变量的值在函数调用结束后不希望值消失,也就是不释放该变量所占用的存储单元;同样,有时在程序设计中也希望某些外部变量只限于被本文件引用,而不能被其他文件引用。这时就需要使用关键词static对变量进行声明。

1、静态局部变量

在局部变量的说明前加上static说明符就构成了静态局部变量。

静态局部变量属于静态存储方式,具有以下特点:

1、静态局部变量在函数内定义,但与自动变量不同,当调用时就已经存在,退出函数时消失。静态局部变量属于静态存储类别,在静态存储区内分配存储单元,在程序整个运行期间都不会释放,静态局部便令始终存储,也就是说它的生存期为整个源程序。

2、静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出函数后,尽管改变量还存在,但不能使用它,如果再次调用其定义的函数,又可以继续使用。

3、对基本类型的静态局部变量,如果在声明时没有赋初始值,则系统自动赋值0。而对于自动变量不赋初值,其值是不确定的。

【示例2.3】使用静态变量

cpp 复制代码
#include <stdio.h>
int add(int x){
    static int n = 0;
    n = n + x;
    return n;
}
int main(){
    int i,j,sum;
    printf("请输入一个整数:\n");
    scanf("%d",&i);
    for (j = 1;  j< i; j++) {
        sum = add(j);
        printf("%d:%d \n",j,sum);
    }
    return 0;

}

上面代码中的静态局部变量n是一种生存期为真个源程序的变量。每次调用add函数时,静态局部变量n都保存了前次被调用后留下的值。如果将static改成auto,那么运行结果是:

因此,从运行结果可以看出,自动变量占动态存储区空间,而不占静态存储区空间,导致每次调用后变量n的值都被释放,每次调用add方法时,n的值都是从0开始。

2 静态全局变量

~未完待续,感谢阅读

相关推荐
落落落sss8 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
简单.is.good26 分钟前
【测试】接口测试与接口自动化
开发语言·python
Yvemil71 小时前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的1 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
我是陈泽1 小时前
一行 Python 代码能实现什么丧心病狂的功能?圣诞树源代码
开发语言·python·程序员·编程·python教程·python学习·python教学
优雅的小武先生1 小时前
QT中的按钮控件和comboBox控件和spinBox控件无法点击的bug
开发语言·qt·bug
虽千万人 吾往矣1 小时前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
创作小达人1 小时前
家政服务|基于springBoot的家政服务平台设计与实现(附项目源码+论文+数据库)
开发语言·python
郭二哈1 小时前
C++——list
开发语言·c++·list
杨荧1 小时前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源