由浅到深认识C语言(6):变量的存储类型

该文章Github地址:https://github.com/AntonyCheng/c-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】

在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!

上一章:由浅到深认识C语言(5):函数

5.变量的存储类别

5.1.内存的分区

可执行文件未运行时所占内存:

bss段:全局未初始化数据

data段:全局初始化数据

text段:代码段

可执行文件运行时所占内存:

堆区:使用malloc , calloc , realloc , free动态申请和释放

栈区:局部变量/数组、函数形参以及函数中大于 4B 的返回值

全局区:全局未初始化数据,全局初始化数据,全局变量和静态变量static bss段和data段)

文字常量区:字符串常量、符号常量

代码区:代码段,二进制代码text段)

各个区域的读写性:

可读可写:堆区、栈区、全局区;

只读:文字常量区、代码区;

5.2.变量类型

普通局部变量

定义形式:在 {} (复合语句)里面定义的普通变量;

void test()
{//复合语句
    int num = 0; //普通变量
}

作用范围:离它最近的大括号之间有效;

void test()
{//复合语句
    int num1 = 0; //普通局部变量 num1 对外层大括号有效
    {
        int num2 = 0; //普通局部变量 num2 对内层大括号有效
    }
    printf("num2 = %d",num2); //这里会报错,找不到 num2 这一个变量
}

生命周期:离它最近的大括号有效,离开大括号的局部变量,系统自动回收;

存储区域:栈区;

注意事项

  1. 普通局部变量不初始化,内容不确定;

  2. 普通局部变量如果同名且不报错的情况下,就近原则;

    void test(){
        int data = 100;
        {
            int data = 200;
            printf("A = %d",data); //这里 A = 200
        }
        printf("B = %d",data); //这里 B = 100
    }
    

    但是我们要杜绝同名的情况;

普通全局变量

定义形式:定义在函数外边的变量,称之为全局变量;

int data; //这里就是普通全局变量
void test(){
    
}
int main(int argc,char *argv){
    
}

作用范围:当前的源文件都有效(可加可不加 extern),如果让这个变量在其他源文件有效的话,必须加上 extern;

#include<stdio.h>
extern int num; //由于 num 在调取函数之间,所以此处要像函数一样声明一下;
//上面的这个代码尽量加一个 extern ,保证代码的可读性;
void test01() {
	printf("test01 中 num = %d\n", num);
}
int num = 100; //这里就是 num 的一个全局变量;
void test02() {
	printf("test02 中 num = %d\n", num);
}
int main(int argc, char* argv[]){
	printf("main 中 num = %d\n", num);
	test01();
	test02();
	return 0;
}
//打印结果都为 num = 100;

生命周期:整个进程都有效,程序结束的时候,全局变量才被释放;

存储区域:全局区;

注意事项

  1. 全局变量不初始化,内容为零,原因是不初始化的话就会被放在bss段,该段会自动置零;

  2. 如果全局变量要在其他源文件中使用,必须在所使用的源文件中加 extern 声明;

  3. 如果全局变量和局部变量同名,在大括号语句中优先使用局部变量;

    int num = 100;
    int main(int argc,char *argv){
        num = 10;
        printf("num = %d",num);//这里打印出来是 num = 10
    }
    

静态局部变量

定义形式:在大括号中定义,前面必须加 static 修饰,这样的变量叫静态全局变量;

#include<stdio.h>
void test() {
	static int num;//静态局部变量;
	return;
}
int main(int argc, char *argv[]) {
	test();
	return 0;
}

作用范围:离它最近的大括号之间有效;

#include<stdio.h>
void test() {
	{
		static int num;//静态局部变量;
	}
	printf("num = %d\n", num);//这里不识别 num
	return;
}
int main(int argc, char *argv[]) {
	test();
	return 0;
}

生命周期:整个进程,程序结束的时候静态局部变量才被释放;

我们来比较一下普通局部变量和静态局部变量:

普通局部变量:

#include<stdio.h>
void test() {
	int num = 10;
	num++;
	printf(" %d ", num);
	return;
}
int main(int argc, char *argv[]) {
	test();
	test();
	test();
	test();
	printf("\n");
	return 0;
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

静态局部量:

#include<stdio.h>
void test() {
	static int num = 10;
	num++;
	printf(" %d ", num);
	return;
}
int main(int argc, char *argv[]) {
	test();
	test();
	test();
	test();
	printf("\n");
	return 0;
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

存储区域:全局区;

注意事项

  1. 静态局部变量如果不初始化,内容为零;
  2. 只能被定义一次(重要);

静态全局变量

定义形式:在函数外边定义,同时加上 static 修饰;

#include<stdio.h>
static data = 10;//静态全局变量
void test() {
	return;
}
int main(int argc, char *argv[]) {
	return 0;
}

作用范围:当前源文件有效,不能在其他源文件使用;

生命周期:整个进程,当程序结束后,静态全局变量才会被识别

存储区域:全局区;

注意事项

  1. 静态全局变量不初始化,内容为零;
  2. 静态全局变量只在当前源文件有效;

5.3.函数类型

全局函数(普通函数)

void test() {
	printf("这就是一个全局函数\n");
	return;
}
  • **特点:**其他源文件可以使用全局函数,但是必须加 extern 声明;

静态函数(局部函数)

static void test() {
	printf("这就是一个静态函数\n");
	return;
}
  • **特点:**其他源文件不可以直接使用静态函数,只能在当前源文件使用;
  • **注意:**如果想在其他源文件直接调用静态函数,需要将静态函数封装在全局函数中,同时全局函数和静态函数必须是同一个源文件,这样可以在其他源文件中直接调用全局函数,然后由全局函数直接调用静态函数;

**案例:**计算;

  • fun1.c

    int va = 7;
    int getG(void){
        int va = 20;
        return va;
    }
    // va = 7(是); getG = 20;(是)
    
  • fun2.c

    static int va = 18;
    static int getG(void){
    	return va;
    }
    int getO(void){
        return getG();
    }
    // va = 18(否); getG = 18(否); getO = 18(是);
    
  • main.c

    #include<stdio.h>
    extern int va;
    extern int getG(void);
    extern int getO(void);
    int main(void){
        printf("va = %d\n",va);				//答案为 7
        printf("getO = %d\n",getO());		//答案为 18
        printf("getG = %d\n",getG());		//答案为 20
        printf("%d\n",va*getO()*getG());	//答案为 2520
    }
    

下一章:由浅到深认识C语言(7):预处理&二进制

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值