C语言变量的作用域

news2024/9/22 9:27:42

所谓作用域(Scope),就是变量的有效范围,就是变量可以在哪个范围以内使用。有些变量可以在所有代码文件中使用,有些变量只能在当前的文件中使用,有些变量只能在函数内部使用,有些变量只能在 for 循环内部使用。

变量的作用域由变量的定义位置决定,在不同位置定义的变量,它的作用域是不一样的。本节我们只讲解两种变量,一种是只能在函数内部使用的变量,另一种是可以在所有代码文件中使用的变量。

在函数内部定义的变量(局部变量)

在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了,我们将这样的变量称为局部变量(Local Variable)。函数的形参也是局部变量,也只能在函数内部使用。请看下面的例子:

#include<stdio.h>

intsum(int m,int n){
int i, sum=0;
//m、n、i、sum 都是局部变量,只能在 sum() 内部使用
for(i=m; i<=n; i++){
        sum+=i;
}
return sum;
}

intmain(){
int begin =5, end =86;
int result =sum(begin, end);
//begin、end、result 也都是局部变量,只能在 main() 内部使用
printf("The sum from %d to %d is %d\n", begin, end, result);

return0;
}

m、n、i、sum 是局部变量,只能在 sum() 内部使用;begin、end、result 也是局部变量,只能在 main() 内部使用。

对局部变量的两点说明:

  • main() 也是一个函数,在 main() 内部定义的变量也是局部变量,只能在 main() 函数内部使用。

  • 形参也是局部变量,将实参传递给形参的过程,就是用实参给局部变量赋值的过程,它和a=b; sum=m+n;这样的赋值没有什么区别。

在所有函数外部定义的变量(全局变量)

C语言允许在所有函数的外部定义变量,这样的变量称为全局变量(Global Variable)。

全局变量的默认作用域是整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件)。如果给全局变量加上 static 关键字,它的作用域就变成了当前文件,在其它文件中就无效了。

【实例】定义一个函数,根据长方体的长宽高求它的体积以及三个面的面积。

#include<stdio.h>

//定义三个全局变量,分别表示三个面的面积
int s1 =0, s2 =0, s3 =0;

intvs(int length,int width,int height){
int v;//体积
    v = length * width * height;
    s1 = length * width;
    s2 = width * height;
    s3 = length * height;
return v;
}

intmain(){
int v =0;
    v =vs(15,20,30);
printf("v=%d, s1=%d, s2=%d, s3=%d\n", v, s1, s2, s3);
    v =vs(5,17,8);
printf("v=%d, s1=%d, s2=%d, s3=%d\n", v, s1, s2, s3);

return0;
}

运行结果:

v=9000, s1=300, s2=600, s3=450

v=680, s1=85, s2=136, s3=40

根据题意,我们希望借助一个函数得到四份数据:体积 v 以及三个面的面积 s1、s2、s3。遗憾的是,C语言中的函数只能有一个返回值,我们只能将其中的一份数据(也就是体积 v)放到返回值中,其它三份数据(也就是面积 s1、s2、s3)只能保存到全局变量中。

C语言代码从前往后依次执行,变量在使用之前必须定义或者声明,全局变量 s1、s2、s3 定义在程序开头,所以在 vs() 和 main() 中都有效。

在 vs() 中将求得的面积放到 s1、s2、s3 中,在 main() 中能够顺利取得它们的值,这说明:在一个函数内部修改全局变量的值会影响其它函数,全局变量的值在函数内部被修改后并不会自动恢复,它会一直保留该值,直到下次被修改。

全局变量也是变量,变量只能保存一份数据,一旦数据被修改了,原来的数据就被冲刷掉了,再也无法恢复了,所以不管是全局变量还是局部变量,一旦它的值被修改,这种影响都会一直持续下去,直到再次被修改。

关于变量的命名

每一段可运行的C语言代码都包含了多个作用域,即使最简单的C语言代码也是如此。

intmain(){
return0;
}

这就是最简单的、可运行的C语言代码,它包含了两个作用域,一个是 main() 函数内部的局部作用域,一个是 main() 函数外部的全局作用域。

C语言规定,在同一个作用域中不能出现两个名字相同的变量,否则会产生命名冲突;但是在不同的作用域中,允许出现名字相同的变量,它们的作用范围不同,彼此之间不会产生冲突。这句话有两层含义:

  • 不同函数内部可以出现同名的变量,不同函数是不同的局部作用域;

  • 函数内部和外部可以出现同名的变量,函数内部是局部作用域,函数外部是全局作用域。

1) 不同函数内部的同名变量是两个完全独立的变量,它们之间没有任何关联,也不会相互影响。请看下面的代码:

#include<stdio.h>

voidfunc_a(){
int n =100;
printf("func_a: n = %d\n", n);
    n =86;
printf("func_a: n = %d\n", n);
}

voidfunc_b(){
int n =29;
printf("func_b: n = %d\n", n);
func_a();//调用func_a()
printf("func_b: n = %d\n", n);
}

intmain(){
func_b();
return0;
}

运行结果:

func_b: n = 29

func_a: n = 100

func_a: n = 86

func_b: n = 29

func_a() 和 func_b() 内部都定义了一个变量 n,在 func_b() 中,n 的初始值是 29,调用 func_a() 后,n 值还是 29,这说明 func_b() 内部的 n 并没有影响 func_a() 内部的 n。这两个 n 是完全不同的变量,彼此之间根本“不认识”,只是起了个相同的名字而已,这就好像明星撞衫,北京和云南都有叫李红的,赶巧了而已。

2) 函数内部的局部变量和函数外部的全局变量同名时,在当前函数这个局部作用域中,全局变量会被“屏蔽”,不再起作用。也就是说,在函数内部使用的是局部变量,而不是全局变量。

变量的使用遵循就近原则,如果在当前的局部作用域中找到了同名变量,就不会再去更大的全局作用域中查找。另外,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量。

下面我们通过一个具体的例子来说明:

#include<stdio.h>

int n =10;//全局变量

voidfunc1(){
int n =20;//局部变量
printf("func1 n: %d\n", n);
}

voidfunc2(int n){
printf("func2 n: %d\n", n);
}

voidfunc3(){
printf("func3 n: %d\n", n);
}

intmain(){
int n =30;//局部变量
func1();
func2(n);
func3();
printf("main n: %d\n", n);

return0;
}

运行结果:

func1 n: 20

func2 n: 30

func3 n: 10

main n: 30

代码中虽然定义了多个同名变量 n,但它们的作用域不同,所有不会产生命名冲突。

下面是对输出结果的分析:

  • 对于 func1(),输出结果为 20,显然使用的是 func1() 内部的 n,而不是外部的 n。

  • 调用 func2() 时,会把 main() 中的实参 n 传递给 func2() 中的形参 n,此时形参 n 的值变为 30。形参 n 也是局部变量,所以就使用它了。

  • func3() 输出 10,使用的是全局变量,因为在 func3() 中不存在局部变量 n,所以编译器只能到函数外部,也就是全局作用域中去寻找变量 n。

  • main() 中 printf() 语句输出 30,说明使用的是 main() 中的 n,而不是外部的 n。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文献阅读笔记 # Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks

《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》 用于快速搭建NLP任务的demo的开源项目sbert的原始论文&#xff0c;star数很多&#xff0c;ACL 2019。资源: pdf | code | doc本文文献完成于 2019 年&#xff0c;因此仅代表当时的数据。相关工作&#xff…

人工智能医学影像行业背景,智能医疗的发展背景

1、人工智能未来的发展前景怎么样&#xff1f; 人工智能医疗行业主要公司&#xff1a;目前国内人工智能医疗行业代表性公司主要有&#xff1a;乐普医疗(300003)、鹰瞳科技(2251.HK)、心玮医疗(06609.HK)、美因基因(IPO中)、推想医疗科技(IPO中)等 本文核心数据&#xff1a;人…

Python爬虫(2)-Selenium控制浏览器

Selenium中提供了不少的方法来操作浏览器 Selenium控制浏览器1.打开浏览器2.打开浏览器后可以控制浏览器前进和后退就使用3.浏览器刷新4.浏览器切换网页窗口5.关闭页面和退出浏览器6.设置窗口大小7.获取窗口位置8.最大化窗口9.最小化窗口11.无窗口运行10.全屏11.屏幕截图12.元素…

opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现

文章目录opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现1. warpAffine 函数处理仿射变换2. warp_perspective3&#xff0c; 实验opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现 1. warpAffine 函数处理仿射变换 仿射矩阵是2 * 3的矩阵。 首…

(深度学习快速入门)第三章第三节5:深度学习必备组件之欠拟合和过拟合

文章目录一&#xff1a;什么是欠拟合和过拟合二&#xff1a;正则化技术&#xff08;1&#xff09;加入正则项①&#xff1a;L1正则项②&#xff1a;L2正则项&#xff08;2&#xff09;Dropout&#xff08;暂退法&#xff09;我们训练模型的目的是为了让模型真正发现一种泛化模式…

个人流媒体服务搭建

简介 主要是个人的流媒体服务器的创建的方式分享 Centos7自建基于HLS的私人直播服务器 相关资源下载 链接&#xff1a;https://pan.baidu.com/s/1zhWFpFRy2v0_lyjA0-AfAg 提取码&#xff1a;yyds 入门操作 实现方法基于nginx和nginx的一个rtmp模块。因为epel源和nginx官…

来源于《高质量C/C++编程》的几道经典面试题

本文介绍几个非常经典的笔试题&#xff0c;原题详细解析&#xff0c;供参考题目1&#xff1a;非法访问内存泄漏题目2&#xff1a;返回栈空间地址问题--非法访问题目3&#xff1a;内存泄漏题目4&#xff1a;非法访问题目1&#xff1a;非法访问内存泄漏 void Getmemory(char* p)…

Apache Doris 系列: 基础篇-使用BitMap函数精准去重(2)

1. 背景 Apache Doris 原有的BitMap函数虽然比较通用&#xff0c; 但在亿级别的BitMap大基数并交计算性能较差&#xff0c;主要是由以下两个原因造成的&#xff1a; 当BitMap的基数过大&#xff0c;大小超过1GB时&#xff0c;网络或者磁盘的处理时间较长BE节点扫描完数据后传…

机器自动翻译古文拼音 - 十大宋词 - 念奴娇 赤壁怀古 苏轼

念奴娇 赤壁怀古 苏轼 大江东去&#xff0c;浪淘尽&#xff0c;千古风流人物。故垒西边&#xff0c;人道是&#xff0c;三国周郎赤壁。乱石穿空&#xff0c;惊涛拍岸&#xff0c;卷起千堆雪。江山如画&#xff0c;一时多少豪杰。 遥想公瑾当年&#xff0c;小乔初嫁了&#xf…

机器自动翻译古文拼音 - 十大宋词 - 扬州慢 淮左名都 姜夔

扬州慢淮左名都 南宋姜夔 淮左名都&#xff0c;竹西佳处&#xff0c;解鞍少驻初程。 过春风十里&#xff0c;尽荠麦青青。 自胡马窥江去后&#xff0c;废池乔木&#xff0c;犹厌言兵。 将黄昏&#xff0c;清角吹寒&#xff0c;都在空城。 杜郎俊赏&#xff0c;算而今重到须惊…

springmvc 整合 thymeleaf 模板引擎

springmvc 整合 thymeleaf 模板引擎 第一步&#xff1a;导入 web.xml 文件 -> <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-ins…

代码随想录算法训练营第31天 二叉树 java :39. 组合总和 40.组合总和II 131.分割回文串

文章目录LeetCode 39. 组合总和本题题解思路LeetCode 40.组合总和II本题题解思路LeetCode 131.分割回文串本题题解思路那么在代码里什么是切割线呢&#xff1f;那么在代码里什么是切割线呢&#xff1f;总结LeetCode 39. 组合总和 本题题解 思路 根据递归三部曲来分析 递归函…

网站如何进行整站优化?

如果要做优化或者选择性优化&#xff0c;一定要区分关键词优化和全站优化&#xff0c;米贸搜整理如下&#xff0c;希望可以帮助到你&#xff1a;一、全站优化的概念:1.一般认为&#xff0c;全站点优化是指通过SEO技术&#xff0c;使其网站成为搜索引擎中的权威站点。当达到效果…

面试汇总-多线程

目录 1、Thread.sleep(0)的作用 2、Synchronized 2.1、特性 2.2、说一说自己对于 synchronized 关键字的了解&#xff1a; 2.3、synchronized关键字的底层原理(JVM如何实现重量级锁) 2.4、Jdk1.6之后对synchronized做的优化 2.4.1、锁粗化 2.4.2、锁消除 2.5、线程池的…

Scala运算符

算术运算符 关系运算符 Java 和 Scala 中关于“”的区别 逻辑运算符 赋值运算符 位运算符 Scala运算符总结 算术运算符 基本与Java一致 对于除号“/”&#xff0c;它的整数除和小数除是有区别的&#xff1a;整数之间做除法时&#xff0c;只保留整 数部分而舍弃小数部分…

JDBC学习笔记(黑马)

目录 一、JDBC快速入门 二、JDBC API详解 &#xff08;一&#xff09;DriverManager &#xff08;二&#xff09;Connection &#xff08;三&#xff09;Statement &#xff08;四&#xff09;ResultSet &#xff08;五&#xff09;PreparedStatement 三、数据库连接池…

前端实现水印的两种方式(DOM和Canvas)

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域新星创作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;系列专栏&#xff1a;vue3从入门…

Python 海象运算符

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人网站&#xff1a;小嗷犬的技术小站 &#x1f34a;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xf…

图纸版本混乱?BOM表管理困难?看SolidWorks PLM如何高效助力产品数据管理

“随着集团的日益壮大&#xff0c;我们越来越重视信息化系统的建设工作&#xff0c;但在研发生产的过程中我们经常会遇到图纸版本混乱、数据查找不便的问题&#xff1b;特别是在产品设计好后&#xff0c;还需要花费很多时间手动整理BOM表&#xff0c;整理期间由于数据量太大&am…

2023年,对人工智能的思考与展望

近些年来&#xff0c;人工智能的话题一次次的冲上热榜&#xff0c;而在前段时间内&#xff0c;chatgpt以及midjourney又一次冲上了热搜&#xff0c;在海内外引起广泛的讨论&#xff0c;我个人在研究了近一个多月的技术文档和文献资料后&#xff0c;也对人工智能的未来有了很多的…