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

news2024/11/19 1:29:24

1 局部变量和全局变量

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

1.1 局部变量

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

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

#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】使用全局变量

 

#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】使用静态变量

#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 静态全局变量

~未完待续,感谢阅读 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1200049.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入研究SVN代码检查的关键工具:svnchecker vs. SonarQube,选择最适合你的代码检查工具

目录 一、SVN代码检查(整合svnchecker)1、创建SVN代码库2、下载安装包3、修改SVN配置4、新建代码检查配置文件(名称自定义)5、hooks目录添加配置文件6、设置只对Java文件进行检查7、测试 二、SonarQube代码检测1、什么是SonarQube2、MySQL数据库的安装3、SonarQube服务端软件安…

Python之函数进阶-函数执行原理

Python之函数进阶-函数执行原理 函数执行流程 C语言中&#xff0c;函数的活动和栈有关。栈是后进先出的数据结构。栈是由底端向顶端生长&#xff0c;栈顶加入数据成为压栈、入栈、栈顶弹出数据称为出栈。 def add(x, y):r x yprint(r)return rdef main():a 1r add(a, 2)r…

Pytorch损失函数、反向传播和优化器、Sequential使用

Pytorch_Sequential使用、损失函数、反向传播和优化器 文章目录 nn.Sequential搭建小实战损失函数与反向传播优化器 nn.Sequential nn.Sequential是一个有序的容器&#xff0c;用于搭建神经网络的模块被按照被传入构造器的顺序添加到nn.Sequential()容器中。 import torch.nn …

【操作系统】1.1 操作系统的基础概念、功能和目标以及特性

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

Mac电脑配置Flutter开发环境

1.进入官网下载页&#xff1a; Flutter SDK releases | Flutter 可以看到有 Windows、macOS、Linux三种系统的下载包 选择macOS&#xff0c;然后点击下载 Stable channel&#xff08;稳定版&#xff09;中的最新版本&#xff0c;下载完成后可以移动到资源库Library中。 2.下载…

使用easyui前端框架构建一个crud应用(看完这篇就够了)

easyui是博主最喜欢的前端框架&#xff0c;因为它提供了多种主题样式和各种好看的ui组件。 这篇文章将会详细地介绍easyui前端框架的使用&#xff0c;通过创建一个crud应用来帮助大家快速掌握easyui的使用。 一、快速开始 这个章节主要介绍easyui前端框架的下载&#xff0c;ea…

Leetcode—680.验证回文串II【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—680.验证回文串II 实现代码 class Solution { public:bool judgeFunc(string s, int left, int right) {while(left < right) {if(s[left] ! s[right]) {return false;}left;right--;}return true;}bool validPalin…

按键精灵中的字符串常用的场景

在使用按键精灵编写脚本时&#xff0c;与字符串有关的场景有以下几种&#xff1a; 1. 用时间字符串记录脚本使用截止使用时间 Dim localTime "2023-11-12 00:15:14" Dim networkTime GetNetworkTime() TracePrint networkTime If networkTime > localTime The…

LeetCode200.岛屿数量

看完题目我还感觉这道题目有点难&#xff0c;没想到20分钟不到就完全靠自己给写出来了。我就是按照自己的想法来&#xff0c;我用一个等大的visit数组来表示grid数组中的这个元素是否被访问过&#xff08;是否已经被判断了是不是岛屿&#xff09;。 先用一个大的循环对grid数组…

threejs(12)-着色器打造烟雾水云效果

一、自己封装水波纹效果 src/main/main01.js import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import gsap from "gsap"; import * as dat from "dat.gui"; import ver…

解决springboot接受buffer文件为null(从picgo上传buffer看springmvc处理过程)

1. 前言&#xff1a; picgo插件的简单开发 上篇文章我们简单写了picgo上传插件&#xff0c;但是当我们测试的时候&#xff0c;发现问题了&#xff0c;后端MultipartFile file接受到的文件为null。 2. 排查问题&#xff1a; 参考的文档 picgo api列表关于multipart form-data中…

U-Mail邮件系统三大安全措施,防止信息泄露!

在当信息化高速发展的今天&#xff0c;国内很多企业业务流程对OA系统、CRM系统、ERP系统、邮件系统等办公应用依赖度越来越高。这些办公应用给企业带来便利的同时也伴随着越来越多的信息安全问题&#xff0c;而在日常的办公场景中&#xff0c;由于内部员工非法泄漏或黑客入侵导…

Qt实现TCP调试助手 - 简述如何在Qt中实现TCP多并发

简介 软件开发中&#xff0c;可能经常会用到TCP调试工具。本人使用QT开发了一款TCP调试工具&#xff0c;方便大家使用。本文章主要介绍下&#xff0c;该工具的功能&#xff0c;以及如何在Qt中实现TCP服务器的并发。 界面展示 安装界面 桌面图标。安装后会生成桌面图标&#…

(三)正点原子I.MX6ULL kernel6.1挂根文件系统

一、概述 移植NXP官方最新的linux kernel&#xff08;linux-imx-lf-6.1.y&#xff09; 移植方法基本参照正点原子教程 移植开发板&#xff1a;正点原子阿尔法2.1 二、添加开发板到内核 进入内核目录下&#xff0c;先修改Makefile 打开终端&#xff1a; cp arch/arm/configs/im…

fastbins_Double Free调试

我大哥给我出了一题pwn heap题&#xff0c;当时现场的时候没解出来&#xff0c;想岔了。事后感概自己还是理解的不够透彻。决定认真再次调试下。用的是2.23版本的how2heap中fastbins_dup.c。 简单用gcc编译下&#xff0c;然后带源码调试&#xff1a; 生成一个a.out的文件&#…

C++ 运算符重载(Complex复数类)

Complex复数类 Complex.h #ifndef COMPLEX_H #define COMPLEX_H#include <iostream> using namespace std;class Complex { private:double real 0; //复数的实部double imag 0; //复数的虚部 public:Complex() default; /*无参构造*/Complex(double r); …

No186.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

解决XFCE桌面VirtualBox透明背景的问题

1 背景 笔者用的是ManjaroXFCE的组合&#xff0c;但是在使用VirtualBox时&#xff0c;会出现透明背景的问题&#xff1a; 然后发现这其实和Kvantum主题有关。下面将进行设置操作&#xff0c;去修正Kvantum相关配置修复该问题。 2 操作流程 打开Kvantum Manager&#xff1a; …

No184.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

Django中如何创建表关系,请求生命周期流程图

Django中ORM创建表关系 如何创建表关系(一对一 &#xff0c; 一对多 &#xff0c; 多对多) 图书表&#xff0c;出版社表&#xff0c;作者表&#xff0c;作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多&#xff0c;出…