从一段代码读懂C/C++变量作用域
2016-09-06 08:48
295 查看
以下代码来自一道面试题,着重考察了C/C++中的变量作用域问题:
代码在三处不同的地方定义了一个同名变量count(由于作用域不同,这3处的count可以视为3个不同的变量,从而可以用a,b,c这种不同的名字加以区分)。
main函数外部定义了一个int型变量count。这是一个全局变量,起作用范围是整个模块(源文件),也可以在其他模块中调用。
main函数体内定义了一个int型变量count。这个变量的作用范围是整个main函数。
main::for语句块中定义了一个int型静态变量count。其作用域为整个for语句块内部。
此外,在main::for::if语句块内引用了1处定义的全局变量。
总结一下发现C/C++中一个模块或者一个语句块构成一个作用域。这里的模块主要是指一个源码文件。而一个语句块可以是函数体,if-else, switch-case,while, for对应的语句块等等。此外,单独一个{}括起来的语句块也可以构成一个作用域。
其实,不只是变量,函数也有作用域的概念。利用extern声明的函数可以作为全局函数在其它源码或者模块中调用;而static声明的函数只能在本模块中调用。
同样,类也有作用域。通过命名空间(namespace)可以实现不同的作用域,通过域操作符::来访问。不过,对于类来说,一般讨论的是访问级别(Access Level),例如public, private, protected等等。将namespace当做一种访问级别或许比视作一种作用域更加合理。
另外,上面提到,单独一个{}括起来的语句块可以构成一个作用域,在其中定义的符号(变量,函数等等)是独立于{}之外的环境的,从而可以在{}内部和外部定义同名变量。{}执行完毕之后,其内部定义的局部变量会被销毁。这一特性可以为我们编程提供一些方便。例如:
语句块内部声明了一个类的实例。当语句块执行完毕,这个类将自动被销毁,而不会在程序的整个生命周期之中都存在。这种技巧在一定程度上可以用来实现垃圾回收(GC)。
#include <stdio.h> int count = 3; int main(void) { printf("%d\n", count); int i, sum, count = 2; printf("In main: count = %d\n", count); for(i=0,sum=0; i<count; i+=2,count++) { static int count = 4; printf("In main::for: count = %d\n", count); count++; if(i%2 == 0) { extern int count; printf("In main::for::if: count = %d\n", count); count++; sum += count; } sum += count; } printf("%d %d\n", count, sum); return 0; }
代码在三处不同的地方定义了一个同名变量count(由于作用域不同,这3处的count可以视为3个不同的变量,从而可以用a,b,c这种不同的名字加以区分)。
main函数外部定义了一个int型变量count。这是一个全局变量,起作用范围是整个模块(源文件),也可以在其他模块中调用。
main函数体内定义了一个int型变量count。这个变量的作用范围是整个main函数。
main::for语句块中定义了一个int型静态变量count。其作用域为整个for语句块内部。
此外,在main::for::if语句块内引用了1处定义的全局变量。
总结一下发现C/C++中一个模块或者一个语句块构成一个作用域。这里的模块主要是指一个源码文件。而一个语句块可以是函数体,if-else, switch-case,while, for对应的语句块等等。此外,单独一个{}括起来的语句块也可以构成一个作用域。
其实,不只是变量,函数也有作用域的概念。利用extern声明的函数可以作为全局函数在其它源码或者模块中调用;而static声明的函数只能在本模块中调用。
同样,类也有作用域。通过命名空间(namespace)可以实现不同的作用域,通过域操作符::来访问。不过,对于类来说,一般讨论的是访问级别(Access Level),例如public, private, protected等等。将namespace当做一种访问级别或许比视作一种作用域更加合理。
另外,上面提到,单独一个{}括起来的语句块可以构成一个作用域,在其中定义的符号(变量,函数等等)是独立于{}之外的环境的,从而可以在{}内部和外部定义同名变量。{}执行完毕之后,其内部定义的局部变量会被销毁。这一特性可以为我们编程提供一些方便。例如:
{ A obj = A(); A.operation(); }
语句块内部声明了一个类的实例。当语句块执行完毕,这个类将自动被销毁,而不会在程序的整个生命周期之中都存在。这种技巧在一定程度上可以用来实现垃圾回收(GC)。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Linux C函数参考手册(PDF版)
- C# partial关键字说明
- Lua中调用C++函数示例
- Lua教程(十七):C API简介
- 简单谈谈lua和c的交互
- Lua教程(一):在C++中嵌入Lua脚本
- C#用链式方法表达循环嵌套
- C#两个相同属性的类赋值方法
- Lua教程(二):C++和Lua相互传递数据示例
- C#中的委托数据类型简介
- C++联合体转换成C#结构的实现方法
- C#编写的艺术字类实例代码
- C#实现打造气泡屏幕保护效果
- 基于C#技术实现身份证识别功能
- 举例讲解C#编程中委托的实例化使用