作用域规则是指代码或数据的有效使用范围。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. 构建第一个maven工程

    一.maven介绍 Maven 是一个强大的项目管理和构建自动化工具,它通过抽象的项目对象模型和构建生命周期模型来对项目及其构建过程进行管理,Maven 最大化的消除了构建的重复,提升了构建的效率与标 ...

  2. ThinkPHP中field 方法与getField 方法的区别。

    做项目的时候遇到了一个问题,框架生成的sql与放到navicat中执行.和页面显示出来的结果不太一样. 排查了很久,也没有找到问题. 出现问题的sql如下. $fuck = M(null, null, ...

  3. HDU5670Machine(抽象进制)

    有一个机器,它有 m (2\leq m\leq 30)m(2≤m≤30) 个彩灯和一个按钮.每按下按钮时,最右边的彩灯会发生一次变换.变换为: 1. 如果当前状态为红色,它将变成绿色: 2.如果当前状 ...

  4. JavaScript中的事件对象

    JavaScript中的事件对象 JavaScript中的事件对象是非常重要的,恐怕是我们在项目中使用的最多的了.在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含这所有与事件有 ...

  5. JavaWeb---总结(十三)使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  6. 在浏览器输入 URL 后会发生什么?超级详细介绍

    一个古老的面试问题:当你在浏览器中输入whosmall.com并且按下回车之后发生了什么? 不过我们不再局限于平常的回答,而是想办法回答地尽可能具体,不遗漏任何细节. 这将是一个协作的过程,所以深入挖 ...

  7. MVC过滤器之 OnActionExcuted

    Controller里 [SendMessage] public Action SendSmsMessage() { var resultExtendInfo=new ResultExtendInfo ...

  8. 三大WEB服务器对比分析(apache ,lighttpd,nginx)

    一.软件介绍(apache  lighttpd  nginx) 1. lighttpd Lighttpd是一个具有非常低的内存开销,cpu占用率低,效能好,以及丰富的模块等特点.lighttpd是众多 ...

  9. bootstrap panel 和table的使用

    一.HTML中的页面内容 <div class="col-sm-12"> <!-- <div class="m-b-md" style= ...

  10. 安装vim的ycm

    环境centos 6.7 vim 7.3 安装vundle Vundle(Vim bundle)是一个Vim的插件管理器.它是把git操作整合进去,用户需要做的只是去GitHub上找到自己想要的插件的 ...