【C语言入门教程】5.2 函数的作用域规则(auto, static)
作用域规则是指代码或数据的有效使用范围。C语言将函数作为独立的代码块,函数之间不能相互访问其内部的代码或数据。函数间数据的传递只能通过接口实现。但是,变量的定义方法可改变函数的作用域规则,可将变量分为 局部变量 和 全局变量 两种。
5.2.1 局部变量
在函数体内定义的变量称为 局部变量,局部变量的作用域仅限于该函数体内。声明局部变量的关键字为 auto,它的一般形式是:
auto 数据类型 变量名;
auto 关键字作为声明语句的默认值,所以通常省略。在函数中定义的局部变量,作用域在该函数体内,如:
void func()
{
int x = 1000;
printf("func()函数内的变量 x 值为:%d\n", x); // 输出为 func() 函数体内变量 x 的值
} int main()
{
int x = 2000;
func();
printf("main() 函数内的变量 x 值为:%d\n", x);
// 输出 main() 函数体内变量 x 的值
return 0;
}
func()函数 和 main() 函数各自定义了一个变量 x,在 func()函数中访问变量 x,则访问的是func()函数体内所定义的变量x。同理,main()函数只能访问其函数体内的变量x。这样,不同函数间的数据被独立起来,保证了数据的安全性。上例的输出为:
func()函数内的变量 x 值为:
main()函数内的变量 x 值为:
在独立的代码块内定义的局部变量,作用域在该代码块内,如下例所示:
int main()
{
int x = 100;
if (x < 150) // 这里引用的是main() 函数中定义的变量 x
{
int x = 200; // 在代码块中定义变量 x
printf("%d", x); // 这里引用的是代码块中定义的变量 x
}
return 0;
}
该程序输出的结果为 200,因为引用的是代码块中的变量x。如果去掉代码快中定义变量x的语句,那么输出的将是 main() 函数的变量x,输出结果为 100。假设在变量的一个作用域内,有同名的另一个变量的作用域,只有一个变量是有效的。如图 9.1 所示,作用域2被包含在作用域1内,2个作用域都定义了变量x。简单地说,定义位置与引用位置相近的变量是有效的,即作用域2内定义的变量x被引用。
5.2.2 全局变量
全局变量的作用域为整个源程序文件,文件中的所有函数或程序块都可以引用。当定义全局变量时,需将变量声明语句放置在所有函数外,如:
#include <stdio.h> int x = 1000;
void func(); int main()
{
printf("%d\n", x); // 引用全局变量 x
x = 2000; // 改变全局 x 的值
func(); // 调用函数 func() return 0;
} void func()
{
printf("%d\n", x); // 引用全局变量 x,此时全局变量 x 的值已被 main() 函数改变过
return;
}
5.2.3 动态存储变量
从变量的生存周期来分类,可将变量分为 动态存储变量 和 静态存储变量。动态存储变量在函数调用时存入内存,函数调用后从内存中删除。声明动态存储变量的关键字为 auto,与声明局部变量相同,它的一般形式是:
auto 数据类型 变量名;
auto 关键字作为声明语句的默认值,所以通常可省略。由于函数中的动态变量会在函数退出时删除,所以两次调用函数时,函数不会保存动态变量的数据。如下例所示:
#include <stdio.h> void func()
{
int x = 100;
printf("%d\n", x);
x += 100;
} int main ()
{
func();
func();
return 0;
}
此程序2次输出的值都是 100.因为即使func()函数第一次调用时改变了变量 x 的值,函数退出后变量x 被从内存中删除,第二次调用函数时又需要重新初始化 x ,所以2次输出的值相同。
还有一种动态存储变量称之为 寄存器变量,寄存器是位于 CPU 内部的存储单元,CPU读取寄存器内的数据极其快捷。因此,将程序中需要大量反复使用的变量设为寄存器变量可提高程序的运行速度。声明寄存器变量
的一般形式为:
register 数据类型 变量名;
寄存器资源非常有限,不同的操作系统 和 C 编译器对寄存器变量的使用有不同的限制。如 GCC 编译器通常限制寄存器变量的数量为 2个,将超过的寄存器变量当做普通动态变量处理。
5.2.4 静态存储变量
在编译时分配存储空间的变量称为静态存储变量。在函数退出时,静态存储变量依然被保留在内存中,再次执行同一函数会得到与上次退出时相同的数值。声明静态存储变量的关键字为 static,声明的一般形式为:
static 数据类型 变量名;
如下代码所示:
#include <stdio.h> void func()
{
static int x = 100; // 声明静态存储变量 x 并赋初值
printf("%d\n", x); // 输出 x 的值,此时变量 x 的值为 100
x += 100; // 改变 x 的值,此时变量 x 的值为 200
} int main ()
{
func(); // 第一次调用函数 func()
func(); // 第二次调用函数 func()
return 0;
}
第一次调用 func() 函数时,声明了静态存储变量 x,并为变量 x 赋初值 100,然后输出变量 x 的值,将变量 x 的值加上 100。func()函数退出后变量 x 仍然存在于内存中,所以第二次调用 func() 函数时,声明变量 x 并赋初值的语言不会被再次执行,因而第二次输出变量的值为 200。
【C语言入门教程】5.2 函数的作用域规则(auto, static)的更多相关文章
- Go语言入门教程(十)之函数
Hello 各位小伙伴大家好,我是小栈君,假期一眨眼就过去了.不知道大家玩的是否开心呢? 上次我们讲到了关于Go语言的流程控制,小栈君也希望小伙伴跟着小栈君一步一个脚印的敲一下代码,相互进步.本期我们 ...
- 《Ruby语言入门教程v1.0》学习笔记-01
<Ruby语言入门教程v1.0> 编著:张开川 邮箱:kaichuan_zhang@126.com 想要学习ruby是因为公司的自动化测试使用到了ruby语言,但是公司关于ruby只给了一 ...
- C语言入门教程-(5)格式化输入输出
1.输入和输出 在程序的使用中,我们经常可以看的这么一个场景:用户需要输入数据,经过程序运算,得到结果后输出.在C语言中,输入数据和输出数据都是由库函数完成的,通过语句来输入/输出. 2.格式化输出— ...
- 《JavaScript语言入门教程》记录整理:入门和数据类型
目录 入门篇 js介绍 历史 基本语法 数据类型 概述 null 和 undefined 数值 字符串 对象 函数 数组 本系列基于阮一峰老师的<JavaScrip语言入门教程>或< ...
- 《JavaScript语言入门教程》记录整理:运算符、语法和标准库
目录 运算符 算数运算符 比较运算符 布尔运算符 二进制位运算符 void和逗号运算符 运算顺序 语法 数据类型的转换 错误处理机制 编程风格 console对象和控制台 标准库 Object对象 属 ...
- 《JavaScript语言入门教程》记录整理:面向对象
目录 面向对象编程 实例对象与 new 命令 this关键字 对象的继承 Object对象的方法 严格模式(strict mode) 本系列基于阮一峰老师的<JavaScrip语言入门教程> ...
- 智能合约语言 Solidity 教程系列3 - 函数类型
Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...
- Linux pwn入门教程(10)——针对函数重定位流程的几种攻击
作者:Tangerine@SAINTSEC 本系列的最后一篇 感谢各位看客的支持 感谢原作者的付出一直以来都有读者向笔者咨询教程系列问题,奈何该系列并非笔者所写[笔者仅为代发]且笔者功底薄弱,故无法解 ...
- c语言该怎么入门?C语言入门教程(非常详细)
C语言是一门面向过程的编译型语言,它的运行速度极快,仅次于汇编语言.C语言是计算机产业的核心语言,操作系统.硬件驱动.关键组件.数据库等都离不开C语言:不学习C语言,就不能了解计算机底层. 这套「C语 ...
随机推荐
- 和redis谈一场恋爱(第二天约会了解彼此)
最近使用了Memcache,带来的便利已经让我欣喜若狂.开启了另一种又快又好的方式存储和读取数据.中间经过了一番折腾,学习了mysql,终于有学到了redis. Redis的全名是Remote Dic ...
- HD1269迷宫城堡(有向图 && 划分连通块)
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 探究JavaScript中的五种事件处理程序
探究JavaScript中的五种事件处理程序 我们知道JavaScript与HTML之间的交互是通过事件实现的.事件最早是在IE3和Netscape Navigator 2中出现的,当时是作为分担服务 ...
- UI学习之常用方法(续)
UIView 1. UIView *vv = [[UIView alloc]initWithFrame:CGRectMake(100,100, 100, 30)]; [vv.layer setB ...
- 【原】web移动端常用知识点笔记
摘要:因为平时搞移动端的比例多一点,做个小小的总结.虽然网上很多这方面的总结,不过还是想自己也总结一下,适合自己的才是最好的.这样也方便以后自己的查阅 viewport模板——通用 <!DOCT ...
- 纯css3实现旋转的太极图
效果图: 代码如下: <!DOCTYPE html> <html> <head lang="zh"> <meta charset=&quo ...
- sp_executesql 使用
sp_executesql 比 之前的exec @sql 区别在可以实现参数的传入传出 如 declare @sql nvarchar(2000) declare @pid varchar(20) s ...
- Jquery 的事件方法
1.$(selector).bind(event,data,function,map) //给元素添加一个事件 2.当元素失去焦点时发生 blur 事件,获得焦点时触发focus事件: $(" ...
- Linux下多线程下载工具 - Axel
Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件.适合网速不给力时多线程下载提高下载速度.比如在国 ...
- jquery实现图片预加载
使用jquery实现图片预加载提高页面加载速度和用户体,本就为大家详细分析jquery图片预加载的实现原理. 什么时候使用图片预加载? 如果页面使用了很多不是最初加载便可见的图片,有必要进行预加载: ...