首页/新闻资讯/正文详情

C语言:作用域、链接与存储期

发布时间:2026/11/6 6:16:10 来源:云帆数科 栏目:资讯中心
C语言:作用域、链接与存储期
相关阅读C语言https://blog.csdn.net/weixin_45791458/category_12423166.html?spm1001.2014.3001.5482目录作用域块作用域变量定义位置函数作用域函数原型作用域​​​​​​​ 特殊情况文件作用域链接无链接内部链接外部链接存储期自动存储期静态存储期动态存储期​​​​​​​线程存储期作用域作用域(Scope)描述程序中标识符的生效区域可访问区域一个C语言变量的作用域可以是块作用域、函数作用域、函数原型作用域、文件作用域。块作用域块是用一对花括号括起来的代码区域例如整个函数体是一个块函数中的复合语句也是一个块。定义在块中的变量具有块作用域块作用域变量的可访问区域是从定义位置到变量所属块结尾。即使没有在代码块中函数的形参也被视为具有块作用域。例1给出了一个简单的例子。// 例1 void func(int t) { // t具有块作用域 int a 10; // a具有块作用域 { int b 20; // b具有子块作用域 } // b的作用域结束 // 这里可以继续使用a和t但不能再使用b }变量定义位置在C90及以前的标准也叫ANSI C中所有具有块作用域的变量必须在块的最开头声明在任何可执行语句比如if、for语句之前例2所示的语句在C90及以前的标准也叫ANSI C中是不合法的。// 例2 void func() { int a 10; printf(%d\n, a); int b 20; // C90标准不允许这样在执行语句后再声明变量 } // 报错error: ISO C90 forbids mixed declarations and code [-Werrordeclaration-after-statement]C99标准放宽了这一限制允许在块中的任意位置声明变量甚至在for语句头中定义变量如例3所示。需要注意的是for语句头中定义的变量和循环块中定义的变量具有块作用域即使循环体没有使用花括号括起来。// 例3 void func() { for (int i 0; i 5; i) { // i具有子块作用域 int square i * i; // square具有子块作用域 } }函数作用域函数作用域是只针对标签名而言的即标签名在整个函数内都有效如例4所示需要注意的是标签名是指goto语句跳转用的标签而不是普通的变量名。// 例4 void func() { label1: // 这是一个标签具有函数作用域 printf(At label1\n); goto label1; // 在函数内任何地方都能跳到label1 }函数原型作用域函数原型作用域用于函数声明中的形参定义范围是从形参定义处到原型声明结束。这意味着编译器在处理函数原型中的形参时只关心它的类型而形参名如果有的话通常无关紧要即使有形参名也不必与函数定义中的形参名相匹配如例5所示。// 例5 int add(int a, int b); // a和b具有函数原型作用域 int add(int x, int y) { // 这里即使参数名换了也没问题 return x y; }特殊情况当变长数组(VLA)出现在函数原型作用域时作为变长数组索引的形参名不能省略如例6所示。同样形参名依旧不必与函数定义中的形参名相匹配。// 例6 int use_a_VLA(int n, int m, int ar[n][m]); // a、b和ar具有函数原型作用域 int use_a_VLA(int x, int y, int br[x][y]) { // 这里即使参数名换了也没问题 return 0; }文件作用域定义在函数外的变量具有文件作用域文件作用域变量的可访问区域至少是从定义位置到变量所属翻译单元(translation unit)的结尾如例7所示这里的“至少”是因为文件作用域变量可以拥有内部链接和外部链接两种属性由于可以被多个函数访问因此文件作用域变量又被称为全局变量。// 例7 // 文件test1.c int var 100; // var具有文件作用域 #include test1.h void global() { int a var; } // 文件test1.h int b var;翻译单元指的是由预处理器完成了所有插入展开后并作为gcc的命令行参数的一个源代码文件。如果gcc的命令行参数有多个文件将在编译、汇编后使用链接器对目标文件(.o)进行链接。链接链接(Linkage)描述程序中标识符在多个翻译单元之间的生效区域可访问区域一个C语言变量的链接属性可以是无链接、内部链接和外部链接。无链接具有块作用域、函数作用域和函数原型作用域的变量都是无链接的意味着这些变量只能在一个翻译单元中的部分区域访问私有。内部链接具有文件作用域的变量可以是内部链接内部链接代表其可以在一个翻译单元内使用如文件作用域一节所述。外部链接具有文件作用域的变量可以是外部链接外部链接代表其可以在多个翻译单元共之间享如例8所示。// 例8 // 文件test1.c extern int var; // var具有文件作用域外部链接 void external_global() { int a var; } // 文件test2.c int var 100; // gcc test1.c test2.c -o my_program存储期作用域和链接描述了变量的生效区域而存储期(Storage Duration)指的是变量在内存/寄存器中存在的时间一个C语言变量的存储期可以是自动存储期、静态存储期、动态存储期和线程存储期。自动存储期块作用域的变量通常具有自动存储期当程序进入定义这些变量的块时为这些变量分配内存但不一定立刻初始化当退出这个块时释放为变量分配的内存。需要注意的是子块的变量一般在函数调用时就会分配内存大部分现代编译器都是这么做的而不是等进入子块时才分配内存在函数返回时才释放内存而不是退出子块就释放内存这也就导致了可以通过指针间接访问如例9所示。​// 例9 void func(int t) { // t具有自动存储期 int *a; // a具有自动存储期 { int b 20; // b具有自动存储期 a b; } printf(%d, *a); // 大部分现代编译器没问题但是不要这么做 }静态存储期如果变量具有静态存储期那么该变量在程序执行期间一直存在。所有具有文件作用域的变量都是具有静态存储期对于具有块作用域的变量如果使用static关键字定义则其具有静态存储期否则其具有自动存储期如例10所示。具有静态存储期的变量只能用常量初始化如果不进行显式初始化则初始化为0。​// 例10 int c; // c具有静态存储期初始化为0 int* func() { int *d; static int a; // a具有静态存储期初始化为0 { static int b 20; // b具有静态存储期初始化为20 d b; } printf(%d, *d); // 没有任何问题 return a; }对于例10而言变量a、b、c都具有静态存储期即变量a、b在程序开始执行时就存在并不是执行到函数时才分配内存但依旧受到作用域的访问限制和例9一样可以使用指针间接访问也可以返回静态存储期变量的指针给其他函数访问。动态存储期使用malloc()函数可以创建动态存储期的内存块完全由程序员管理因此需要记得在使用完毕后用free()函数释放否则会造成内存泄漏如例11所示。// 例11 void func() { int *d; { d (int*)malloc(sizeof(int)); *d 20; } printf(%d\n, *d); free(d); }线程存储期线程存储期用于并发程序设计程序可创建多个子线程每个线程拥有属于自己的专属变量该变量在线程结束时释放使用_Thread_local关键字定义C11标准引入如例12所示。// 例12 #include stdio.h #include pthread.h _Thread_local int x 0; // 每个线程有自己的x void* thread_func(void* arg) { x; printf(Thread %d: x %d\n, *(int*)arg, x); return NULL; } int main() { pthread_t t1, t2; int id1 1, id2 2; pthread_create(t1, NULL, thread_func, id1); pthread_create(t2, NULL, thread_func, id2); pthread_join(t1, NULL); pthread_join(t2, NULL); return 0; }

相关推荐

GSYVideoPlayer:Android 视频播放从接入到切换内核的实践笔记
GSYVideoPlayer:Android 视频播放从接入到切换内核的实践笔记

GSYVideoPlayer:Android 视频播放从接入到切换内核的实践笔记 【免费下载链接】GSYVideoPlayer Video players (IJKplayer, ExoPlayer, MediaPlayer), HTTPS, 16k page size, danmaku (bullet chat) support, external subtitles, support for filters, watermarks,… · 2026/11/6 6:15:10

Leon Sans 快速入门:3 步把动态字重和文字动画画进网页
Leon Sans 快速入门:3 步把动态字重和文字动画画进网页

Leon Sans 快速入门:3 步把动态字重和文字动画画进网页 【免费下载链接】leonsans Leon Sans is a geometric sans-serif typeface made with code in 2019 by Jongmin Kim. 项目地址: https://gitcode.com/gh_mirrors/le/leonsans Leon Sans 是一个用 JavaS… · 2026/11/6 6:15:10

光伏电站、风机点位空间分布数据集整理
光伏电站、风机点位空间分布数据集整理

光伏电站/光伏面板 1. 基于GEE和Sentinel-2用随机森林分类算法生成的全国2020年10m分辨率光伏电站数据 A 10-m national-scale map of ground-mounted photovoltaic power stations in China of 2020 数据分省存放,因为数据是分辨率较高的栅格数据类型&#xff0… · 2026/11/6 6:15:10

Unity中旋转矩形最小外接矩形计算与优化
Unity中旋转矩形最小外接矩形计算与优化

1. 问题背景与需求拆解在Unity游戏开发中,我们经常会遇到需要计算物体包围盒的场景。最近我在开发一个2D物理引擎的扩展功能时,遇到了一个具体需求:给定两个任意旋转角度的矩形,需要计算出能够同时包含它们的最小外接矩形。这个需… · 2026/11/6 7:01:25

SAP Fiori磁贴信息(Tile Information)全解析与应用实践
SAP Fiori磁贴信息(Tile Information)全解析与应用实践

1. 为什么每个SAP Fiori开发者都应该掌握Tile Information第一次接触SAP Fiori Launchpad时,我完全被那些五彩缤纷的磁贴(tile)迷住了。直到有一天,业务用户反馈某个关键应用入口在手机上不显示,而开发环境明明配置正常。花了整整两天时间排查… · 2026/11/6 7:01:25

解决《文明6》ModBuddy开发中的路径配置错误
解决《文明6》ModBuddy开发中的路径配置错误

1. 问题背景与错误解析最近在制作《文明6》"义和团"模组时,遇到了一个典型的路径配置错误:"The GeneratePantryPaths task was not given a value for the required parameter AssetsPath"。这个错误看似简单,实则涉及Mo… · 2026/11/6 7:01:25

SpreadJS V19.0实时协同表格技术解析与应用
SpreadJS V19.0实时协同表格技术解析与应用

1. SpreadJS V19.0 协同插件深度解析作为一名长期从事企业级Web应用开发的前端工程师,我深知表格协作在业务场景中的重要性。SpreadJS V19.0协同插件的发布,确实为团队协作带来了革命性的改变。让我们从技术实现角度,深入剖析这个解决方案的核… · 2026/11/6 7:01:25

OpenCode与oh-my-opencode:开源AI编程工具链实战指南
OpenCode与oh-my-opencode:开源AI编程工具链实战指南

1. 开源AI编程工具链的革命性组合在开发者社区中,最近出现了一个令人兴奋的技术组合——OpenCode与oh-my-opencode的协同使用。这个组合正在重新定义我们进行AI辅助编程的方式。作为一名长期关注开发者工具演进的技术博主,我第一次接触这套工具链时就意识… · 2026/11/6 7:01:25

批处理for循环的数值迭代写法
批处理for循环的数值迭代写法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 7:00:25

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07

三菱PLC数据采集到数据库的时序设计:Python+MC协议实战
三菱PLC数据采集到数据库的时序设计:Python+MC协议实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11

ASIC主模式RTL设计:状态机与三态驱动的流片级实现
ASIC主模式RTL设计:状态机与三态驱动的流片级实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11

STM32嵌入式C++开发:GDB调试与Renode仿真实战指南
STM32嵌入式C++开发:GDB调试与Renode仿真实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码