一文搞懂C语言static关键字的三个作用

目录
  • static修饰局部变量
  • static 修饰全局变量
  • static 修饰函数
  • 总结

static修饰局部变量

图一:test 函数里面定义的 a 是局部变量,局部变量在栈区上开辟空间,栈区的使用特点是进入变量的生命周期时自动为其开辟空间,离开变量的生命周期时自动销毁对应空间,所以这里每次调用 test 函数时 a 都会被重新定义并初始化为0,所以屏幕上打印的是10个1;

图二:我们把 a 用 static 修饰后发现屏幕打印的是1到10,就好像每次调用完 test 函数后 a 并没有被销毁,而是继续使用,下次调用 test 函数时 a 直接在之前的基础上进行 ++ 操作。
所以 static 修饰局部变量的作用是:改变局部变量的生命周期,本质上是改变了局部变量的存储位置,让局部变量不再是在栈区上开辟空间,而是直接在静态区上开辟空间,从而使得局部变量拥有和全局变量一样的生命周期,即随着整个程序生成和销毁。

更深入的理解 static 修饰局部变量的作用:图三,我们的程序从源文件(.c文件)变成可执行程序(.exe文件)需要经过编译链接运行三个环节,而编译环节又分为预处理、编译、汇编三个阶段,在汇编阶段,编译器会把我们的C语言代码转换成汇编代码,而每一条C语言语句都对应着多句汇编代码,然而在图三中,我们可以观察到,只有 static int a = 0; 这条语句没有对应的汇编代码,也就是说,C语言在编译的时候会直接跳过这条语句。
本质上是:在编译环节的编译阶段编译器就会为被 static 修饰的局部变量分配空间,所以C程序在运行的过程中会直接跳过 static 修饰的语句,也就是说,在第二次及以上甚至第一次调用 test 函数时 static int a = 0; 这条语句都不会被执行。

static 修饰全局变量

图一图二对比分析:我在Add.c中定义了一个全局变量g_val,因为全局变量具有外部链接属性,所以我只需要在test.c中对g_val进行声明之后就可以正常使用了,但是当我用 static 来修饰g_val时,我们发现,编译器说g_val是无法解析的外部符号;
所以 static 修饰全局变量的作用是:改变了全局变量的外部链接属性(可以在其他源文件内被访问),使其变成内部连接属性(只能在本文件内部被访问),给我们的感觉是全局变量的作用域变小了。

static 修饰函数

图一图二对比分析:这里和 static 修饰全局变量非常类似,我在Add.c中定义了一个Add函数,因为函数也具有外部链接属性,所以我只需要在test.c中对Add函数进行声明之后就可以正常使用了,但是当我用 static 来修饰Add函数时,我们发现,编译器说Add是无法解析的外部符号;
所以 static 修饰函数的作用是:改变了函数的外部链接属性(可以在其他源文件内被访问),使其变成内部连接属性(只能在本文件内部被访问),给我们的感觉是函数的作用域变小了。

总结

  • static 修饰局部变量的作用:改变局部变量的生命周期,本质上是改变了局部变量的存储位置,让局部变量不再是在栈区上开辟空间,而是直接在静态区上开辟空间,从而使得局部变量拥有和全局变量一样的生命周期,即随着整个程序生成和销毁。
  • static 修饰全局变量的作用:改变了全局变量的外部链接属性(可以在其他源文件内被访问),使其变成内部连接属性(只能在本文件内部被访问)。
  • static 修饰函数的作用是:改变了函数的外部链接属性(可以在其他源文件内被访问),使其变成内部连接属性(只能在本文件内部被访问)。

到此这篇关于一文搞懂C语言static关键字的三个作用的文章就介绍到这了,更多相关C语言static关键字内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c语言static关键字用法详解

    目录 1.static修饰全局变量 2.static修饰函数 3.static修饰局部变量 总结: 1.static修饰全局变量 我们创建两个源文件,一个test.c,一个main.c 现在我们在test.c文件下定义一个全局变量 int g_val = 100; 我们在main.c下进行调用打印g_val我们能访问到g_val吗? 答案是可以的 如果给g_val加上static修饰我们还能再main.c下访问到吗? static int g_val = 100; 这时候答案是不行的! 因此我们

  • C语言Static 关键字解析

    目录 01简述 02static关键字作用 01简述 static关键字在嵌入式C语言当中很简单,它有三个作用: 作用一:在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变. void test1(void) {     unsigned char a:     static unsigned char b:     -     a++:     b++: } 在这个例子中,变量a是局部变量,变量b为局部静态变量.作用一说明了局部静态变量b的特性:在函数体,一个被声明为静态的变量

  • 一文搞懂C语言static关键字的三个作用

    目录 static修饰局部变量 static 修饰全局变量 static 修饰函数 总结 static修饰局部变量 图一:test 函数里面定义的 a 是局部变量,局部变量在栈区上开辟空间,栈区的使用特点是进入变量的生命周期时自动为其开辟空间,离开变量的生命周期时自动销毁对应空间,所以这里每次调用 test 函数时 a 都会被重新定义并初始化为0,所以屏幕上打印的是10个1: 图二:我们把 a 用 static 修饰后发现屏幕打印的是1到10,就好像每次调用完 test 函数后 a 并没有被销毁

  • 一文读懂c++之static关键字

    一.静态变量 与C语言一样,可以使用static说明自动变量.根据定义的位置不同,分为静态全局变量和静态局部变量. 全局变量是指在所有花括号之外声明的变量,其作用域范围是全局可见的,即在整个项目文件内都有效.使用static修饰的全局变量是静态全局变量,其作用域有所限制,仅在定义该变量的源文件内有效,项目中的其他源文件中不能使用它. 块内定义的变量是局部变量,从定义之处开始到本块结束处为止是局部变量的作用域.使用static修饰的局部变量是静态局部变量,即定义在块中的静态变量.静态局部变量具有局

  • 一文搞懂Go语言中条件语句的使用

    目录 if语句 if...else 语句 if 语句嵌套 switch 语句 Type Switch fallthrough select 语句 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. Go 语言提供了以下几种条件判断语句: 语句 描述 if 语句 if 语句 由一个布尔表达式后紧跟一个或多个语句组成. if...else 语句 if 语句 后可以使用可选的 else 语句, else 语

  • 一文搞懂Go语言中文件的读写与创建

    目录 1. 文件的打开与关闭 1.1 os.open 1.2 os.OpenFile() 指定模式打开文件 2. 文件的读取 2.1 打开文件的方式读取文件中的数据 2.2 使用 bufio 整行读取文件 3. 写入文件操作 3.1 file.Write 与 file.WriteString 3.2 bufio.NewWriter 3.3 ioUtil 工具类 1. 文件的打开与关闭 1.1 os.open os.open 函数能打开一个文件 调用 close() 方法 关闭文件 //打开文件

  • 一文搞懂Go语言操作Redis的方法

    目录 前言 安装依赖包 连接redis redis连接池 总结 前言 Redis是一个开源的内存数据库,在项目开发中redis的使用也比较频繁,本文介绍了Go语言中go-redis库的基本使用.感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助. 安装依赖包 Go语言中使用第三方库go-redis go-redis支持连接哨兵及集群模式的Redis. 使用以下命令下载并安装: go get -u github.com/go-redis/redis/v8 连接redis 新建go文件,在项目中引入

  • 一文带你搞懂C语言预处理宏定义

    目录 预定义符号 #define #define 定义标识符 #define 定义宏 替换规则 # 和## 预定义符号 这些预定义符号都是语言内置的 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义 VS环境下未定义__STDC__ ,说明Visual Studio并未完全遵循ANSI C. #define #defi

  • 一文带你搞懂C语言动态内存管理

    目录 一.malloc函数和free函数 二.calloc函数与malloc函数的异同 三.柔性数组 一.malloc函数和free函数 (1) 这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针. 如果开辟成功,则返回一个指向开辟好空间的指针. 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查. 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定. 如果参数 size为0,malloc的行为是标准是未

  • 一文搞懂JAVA 修饰符

    Java语言提供了很多修饰符,主要分为以下两类: 访问修饰符 非访问修饰符 修饰符用来定义类.方法或者变量,通常放在语句的最前端.我们通过下面的例子来说明: public class ClassName { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String[] argum

  • 一文搞懂Java中的序列化与反序列化

    目录 序列化和反序列化的概念 应用场景 序列化实现的方式 继承Serializable接口,普通序列化 继承Externalizable接口,强制自定义序列化 serialVersionUID的作用 静态变量不会被序列化 使用序列化实现深拷贝 常见序列化协议对比 小结 序列化和反序列化的概念 当我们在Java中创建对象的时候,对象会一直存在,直到程序终止时.但有时候可能存在一种"持久化"场景:我们需要让对象能够在程序不运行的情况下,仍能存在并保存其信息.当程序再次运行时 还可以通过该对

  • 一文搞懂JAVA 枚举(enum)

    Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等. Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割. 例如定义一个颜色的枚举类. enum Color { RED, GREEN, BLUE; } 以上枚举类 Color 颜色常量有 RED, GREEN, BLUE,分别表示红色,绿色,蓝色. 使用实例: enum Color { RED, GREEN, BLUE; } public c

随机推荐