作用域规则是指代码或数据的有效使用范围。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)的更多相关文章

  1. Go语言入门教程(十)之函数

    Hello 各位小伙伴大家好,我是小栈君,假期一眨眼就过去了.不知道大家玩的是否开心呢? 上次我们讲到了关于Go语言的流程控制,小栈君也希望小伙伴跟着小栈君一步一个脚印的敲一下代码,相互进步.本期我们 ...

  2. 《Ruby语言入门教程v1.0》学习笔记-01

    <Ruby语言入门教程v1.0> 编著:张开川 邮箱:kaichuan_zhang@126.com 想要学习ruby是因为公司的自动化测试使用到了ruby语言,但是公司关于ruby只给了一 ...

  3. C语言入门教程-(5)格式化输入输出

    1.输入和输出 在程序的使用中,我们经常可以看的这么一个场景:用户需要输入数据,经过程序运算,得到结果后输出.在C语言中,输入数据和输出数据都是由库函数完成的,通过语句来输入/输出. 2.格式化输出— ...

  4. 《JavaScript语言入门教程》记录整理:入门和数据类型

    目录 入门篇 js介绍 历史 基本语法 数据类型 概述 null 和 undefined 数值 字符串 对象 函数 数组 本系列基于阮一峰老师的<JavaScrip语言入门教程>或< ...

  5. 《JavaScript语言入门教程》记录整理:运算符、语法和标准库

    目录 运算符 算数运算符 比较运算符 布尔运算符 二进制位运算符 void和逗号运算符 运算顺序 语法 数据类型的转换 错误处理机制 编程风格 console对象和控制台 标准库 Object对象 属 ...

  6. 《JavaScript语言入门教程》记录整理:面向对象

    目录 面向对象编程 实例对象与 new 命令 this关键字 对象的继承 Object对象的方法 严格模式(strict mode) 本系列基于阮一峰老师的<JavaScrip语言入门教程> ...

  7. 智能合约语言 Solidity 教程系列3 - 函数类型

    Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...

  8. Linux pwn入门教程(10)——针对函数重定位流程的几种攻击

    作者:Tangerine@SAINTSEC 本系列的最后一篇 感谢各位看客的支持 感谢原作者的付出一直以来都有读者向笔者咨询教程系列问题,奈何该系列并非笔者所写[笔者仅为代发]且笔者功底薄弱,故无法解 ...

  9. c语言该怎么入门?C语言入门教程(非常详细)

    C语言是一门面向过程的编译型语言,它的运行速度极快,仅次于汇编语言.C语言是计算机产业的核心语言,操作系统.硬件驱动.关键组件.数据库等都离不开C语言:不学习C语言,就不能了解计算机底层. 这套「C语 ...

随机推荐

  1. 对WEB标准以及W3C的理解与认识

    按照习惯的理解,这两个概念似乎都是指的一个东西(就是咱们在这个版里讨论的这些个"高深理论“^_^).但我认为,事实上从技术的角度上讲,这两个事物几乎没有任何相关性.web标准简而言之就是将页 ...

  2. 十分钟入门less(翻译自:Learn lESS in 10 Minutes(or less))

    十分钟入门less(翻译自:Learn lESS in 10 Minutes(or less)) 注:本文为翻译文章,因翻译水平有限,难免有缺漏不足之处,可查看原文. 我们知道写css代码是非常枯燥的 ...

  3. omnet++5.0安装使用

    1.下载Windows安装包,5.0的omnetpp-5.0-src-windows.zip 2.解压到d盘 3.D:\omnetpp-5.0\doc找到这个目录,下面有个InstallGuide.p ...

  4. VGA 视频输出

    VGA Video Output by Nathan Ickes Introduction VGA is a high-resolution video standard used mostly fo ...

  5. jpa datasource config

    application.properties spring.datasource.driverClassName= spring.datasource.url= spring.datasource.u ...

  6. Java多线程——线程范围内共享变量

    多个线程访问共享对象和数据的方式 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. package java_ ...

  7. Java——jar命令

    把*.class压缩成一个文件,这样的文件就称为jar文件. 如果想要生成jar文件,直接使用JDK中bin目录里的jar.exe就可以将所有的类文件进行压缩. 当用户得到一个jar文件后,即可通过设 ...

  8. 为什么可以用while(cin)?

    为什么可以用while(cin)?   /** * @brief The quick-and-easy status check. * * This allows you to write const ...

  9. 《深入理解bootstrap》读书笔记:第4章 CSS组件(下)

    十. 标签(.label类,label-xxx) 高亮一些标题部分. 1 2 3 4 5 6 <h1>HELLO<span class="label label-defau ...

  10. My latest news (--2016.10)

    2016.10.31 22:44 一个“程序”,打代码占40%.思考占60% 2016.10.30 20:53 周末,话说今天有晚上讲座,还点名,了,悲催.之前学习的Qt有点问题,悲催.推荐个博文:h ...