当前位置: 首页 > news >正文

static 和 extern 关键字

目录

一、static 和 extern 概述

二、作用域与生命周期概念

1、作用域(scope)

2、生命周期(lifetime)

局部变量的生命周期:

全局变量的生命周期:

三、static 修饰局部变量

对比示例分析

代码1:普通局部变量

代码2:static局部变量

关键结论

1、存储位置变化:

2、生命周期变化:

3、初始化特性:

四、static 修饰全局变量

对比示例分析

代码1:普通全局变量

代码2:static全局变量

关键结论

1、链接属性变化:

2、访问范围限制:

3、避免命名冲突:

五、static 修饰函数

对比示例分析

代码1:普通函数

代码2:static函数

关键结论

1、链接属性变化:

2、访问范围限制:

3、封装性优势:

六、总结对比表(超重要!!!)


一、static 和 extern 概述

static 和 extern 都是C语言中的关键字,具有重要的变量和函数修饰作用。

  • static:表示"静态的",可以用于:修饰局部变量、修饰全局变量、修饰函数

  • extern:用于声明外部符号,使得跨文件访问变量和函数成为可能。


二、作用域与生命周期概念

在深入理解 static 和 extern 之前,需要明确两个重要概念:

1、作用域(scope)

作用域是指程序中变量或函数名有效的代码范围。

  1. 局部变量的作用域:仅限于定义它的函数或代码块内部

  2. 全局变量的作用域:从定义点开始到文件末尾,且可通过 extern 声明扩展到整个工程

2、生命周期(lifetime)

生命周期指变量从创建(内存分配)到销毁(内存回收)的时间段。

局部变量的生命周期

  • 进入作用域时创建

  • 离开作用域时销毁

  • 每次进入作用域都会重新初始化

全局变量的生命周期

  • 程序启动时创建

  • 程序结束时销毁

  • 整个程序运行期间持续存在


三、static 修饰局部变量

对比示例分析

代码1:普通局部变量

#include <stdio.h>void test() {int i = 0;  // 每次调用都会重新初始化i++;printf("%d ", i);
}int main() {for(int i = 0; i < 5; i++) {test();}return 0;
}

        在代码1的test函数中,每次调用时都会先创建局部变量i并初始化为0。随后执行i++操作并打印结果,当函数执行完毕时,该变量的生命周期结束,内存将被释放。

代码2:static局部变量

#include <stdio.h>void test() {static int i = 0;  // 只初始化一次i++;printf("%d ", i);
}int main() {for(int i = 0; i < 5; i++) {test();}return 0;
}

        在代码2的输出结果中,我们可以观察到变量i的值具有累加特性。这是因为test函数中的变量i在创建后并不会随着函数执行结束而销毁,当再次进入函数时,系统不会重新创建变量i,而是会继续使用之前累积的数值进行计算。

关键结论

1、存储位置变化

  • 普通局部变量存储在栈区static局部变量存储在静态区

2、生命周期变化

  • static修饰使局部变量的生命周期延长至整个程序运行期间

  • 但作用域保持不变,仍然只能在定义它的函数内访问

3、初始化特性

  • static局部变量只初始化一次

  • 程序运行时在静态区分配内存并初始化

  • 后续函数调用会保持上次的值

使用建议当需要在函数调用之间保持变量值时,使用static修饰局部变量。


四、static 修饰全局变量

对比示例分析

代码1:普通全局变量

add.c:

int g_val = 2018;  // 全局变量定义

test.c:

#include <stdio.h>extern int g_val;  // 外部变量声明int main() {printf("%d\n", g_val);return 0;
}

正常运行,输出:2018

代码2:static全局变量

add.c:

static int g_val = 2018;  // 静态全局变量

test.c:

#include <stdio.h>extern int g_val;  // 外部声明无效int main() {printf("%d\n", g_val);  // 链接错误return 0;
}

    extern用于声明外部符号。当某个全局符号在A文件中定义,而B文件需要使用时,可以通过extern进行声明后直接调用。

编译时会出现链接错误,提示未定义的g_val引用。

关键结论

1、链接属性变化

  • 普通全局变量具有外部链接属性(external linkage)

  • static全局变量具有内部链接属性(internal linkage)

2、访问范围限制

  • static修饰使全局变量仅限于定义它的源文件内部使用

  • 其他文件即使使用extern声明也无法访问

3、避免命名冲突

  • static全局变量不会与其他文件的同名全局变量冲突

使用建议当需要限制全局变量仅在当前文件内使用时,使用static修饰。


五、static 修饰函数

对比示例分析

代码1:普通函数

add.c:

int Add(int x, int y) {return x + y;
}

test.c:

#include <stdio.h>extern int Add(int x, int y);  // 函数声明int main() {printf("%d\n", Add(2, 3));return 0;
}

正常运行,输出:5

代码2:static函数

add.c:

static int Add(int x, int y) {return x + y;
}

test.c:

#include <stdio.h>extern int Add(int x, int y);  // 声明无效int main() {printf("%d\n", Add(2, 3));  // 链接错误return 0;
}

        其实 static 修饰函数和 static 修饰全局变量是一模一样的,所以编译时会出现链接错误,提示未定义的Add函数引用。

关键结论

1、链接属性变化

  • 普通函数默认具有外部链接属性

  • static函数具有内部链接属性

2、访问范围限制

  • static函数只能在定义它的源文件内部调用

  • 对其他文件不可见,即使使用extern声明

3、封装性优势

  • 可以隐藏实现细节

  • 避免与其他文件的同名函数冲突

使用建议当需要限制函数仅在当前文件内使用时,使用static修饰。


六、总结对比表(超重要!!!)

特性static局部变量static全局变量static函数
存储位置静态区静态区代码区
作用域定义它的函数内定义它的文件内定义它的文件内
生命周期整个程序运行期整个程序运行期N/A
链接属性不适用内部链接内部链接
主要用途保持函数调用间的状态文件内部使用的全局数据文件内部使用的函数

        理解static和extern的关键在于掌握变量的存储位置、作用域和链接属性这三个核心概念。合理使用这些关键字可以提高代码的封装性和模块化程度。

http://www.dtcms.com/a/330052.html

相关文章:

  • 公用表表达式和表变量的用法区别?
  • 【SpringBoot】12 核心功能-配置文件详解:Properties与YAML配置文件
  • WinForm中C#扫描枪功能实现(含USB串口)
  • 终端安全检测与防御
  • 20250813比赛总结
  • C++ list模拟实现
  • 未来AI:微算法科技(NASDAQ:MLGO)开发基于忆阻器网络储层计算MemristorPattern虚拟平台
  • 精准阻断内网渗透:联软科技终端接入方案如何“锁死”横向移动?
  • 科技赋能虚拟形象:3D人脸扫描设备的应用与未来
  • 钻井泥浆搅拌机的设计cad1张三维图+设计说明书
  • ULN2003与ULN2803的区别
  • MySQL优化常用的几个方法
  • 0813 网络编程基础
  • docker 容器内编译onnxruntime
  • cisco无线WLC flexconnect配置
  • 【Virtual Globe 渲染技术笔记】4 椭球面上的曲线
  • 大数据可视化设计 | 智能家居 UI 设计:从落地方法到案例拆解
  • 室外 3DVG 基准
  • mysql - 查询重复数据,不区分大小重复问题解决
  • Redis的基础命令
  • 玳瑁的嵌入式日记D17-08013(linux)
  • Java多线程进阶-从乐观锁到读写锁
  • 项目可手撕题目详解
  • 【数字孪生系列】数字孪生引擎中的地标建筑管理系统
  • rar压缩包python解压
  • Go语言网络故障诊断与调试技巧:从入门到实战
  • AMD KFD的BO设计分析系列 0:开篇
  • redis分布式锁封装 redis分布式锁实现 封装Spring工具Redis工具类 redis操作类封装 redis锁封装 redis分布式锁封装
  • 【SpringBoot系列-02】自动配置机制源码剖析
  • Promise.all使用