C/C++语言中的变量分为全局变量和局部变量。

这样的划分方式的根据是变量的可见范围或者叫做作用域。

1 局部变量

局部变量指的是定义在{}中的变量,其作用域也在这个范围内。尽管常见的局部变量都是定义在函数体内的,也全然能够人为的添加一对大括号来限定变量作用域。

例如以下所看到的:

void f()
{
float x = 0;
{
int a;
}
}

别小看这个作用域问题。这对于C++的影响远比纯C要大。C语言中局部变量离开作用域时。编译器会插入一个POP 指令来清理变量占用的栈空间。而在C++中,除了POP指令,还要调用析构函数。

class MyClass
{
MyClass(){}
~MyClass(){}
}; void f()
{
{
MyClass a;
} // 此处会C++编译器被插入调用~MyClass()的代码
do_someting();
}

C++编译器在对象a的作用域结束之前,自己主动插入调用~MyClass()的汇编代码。

局部变量作用域是由编译器强制实施的,这样一旦出现作用域外訪问。编译时就会报错,从而帮助程序猿排除错误。

2 全局变量

全局变量的作用域是整个project。也就是在全部參与链接的文件里都是可见的。这就会导致一个问题-名称冲突。

比如以下project中有3个源文件main.c, 1.c, 2.c。

main.c

#include <stdio.h>
int main(int argc, char** argv)
{
return 0;
}

1.c

int a = 1;

2.c

int a = 2;

编译每一个文件都是能够通过的,可是链接时会报错,由于1.c和2.c使用了同一个名称的全局变量。为此。C语言的全局变量被给予了极坏的形象。甚至不使用全局变量的教条在非常大范围内盛行。

然而全局变量在非常多时候还是必须的,至少是使用它会让问题变得方便。比如当一个变量是非常多函数的參数时。

void f1(int a);
void f2(int a);
void f3(int a);

这样每次调用函数都须要传递这个变量a,当这样的參数个数增多时,会让人变得发狂。如

void f1(int a, int b, int c, int d, int e);
void f2(int a, int b, int c, float g);
void f3(int a, int b, int c, int d);

这样的情况在须要保存状态的程序中非经常见。如GDI库。OpenGL库等。

此时採用全局变量来维护状态数据是非常好的选择。

C++看到了这样的须要。所以索性把这些状态数据和算法函数绑定到了一起,形成了类的概念。从而简化了代码设计。

3 文件级变量

非常多时候,事实上程序猿须要变量的可见范围既不是整个project。也不是函数内部,而是在当前文件里可见。C语言为此提供了静态全局变量。

static global variable。这个名称全然没有能够反映出变量作用域的范围。是一个非常糟糕的名字。

并且起关键字static更是让人摸不着头脑。

static int a = 100;

C语言的设计者也许是为了节省关键字的使用,非常多关键字用在不同的地方都有全然不同的含义。这样的设计应该是仁者见仁的事情,我个人认为假设此处使用其它的关键字如internal来标识,会更easy让人理解。

internal int a = 100;

好像在C#中确实存在相似的关键字来表示作用域。

言归正传,static 修饰的全局变量仅仅在定义它的文件内部有效。其它文件内无法引用它。上面的样例改为:

main.c

#include <stdio.h>
int main(int argc, char** argv)
{
return 0;
}

1.c

static int a = 1;

2.c

int a = 2;

此时,项目会链接成功。由于全局范围内仅仅有一个名为a值为2的全局变量,值为1的那个a仅仅在1.c内有效。

4 C和C++编译器对const常量的一点不同

C++编译器对const常量会自己主动添加static关键字。使其作用域为文件级别。而C语言编译器则不会。

例如以下代码:

main.c

#include <stdio.h>
int main(int argc, char** argv)
{
return 0;
}

1.c

const int a = 1;

2.c

int a = 2;

使用C++编译器能够顺利编译链接成功,可是使用C编译器则在连接时报错。

为了代码的可移植性。不妨手动把 static const都写上。

main.c

#include <stdio.h>
int main(int argc, char** argv)
{
return 0;
}

1.c

static const int a = 1;

2.c

int a = 2;

上述代码则在C和C++编译器下均可编译链接成功。

C/C++语言中变量作用域:局部变量,全局变量,文件级变量的更多相关文章

  1. C语言中的作用域、链接属性与存储属性

    C语言中的作用域.链接属性与存储属性 一.作用域(scope) 代码块作用域 表示{}之间的区域,下例所示,a可以在不同的代码块里面定义. #include<stdio.h> int ma ...

  2. JS中的作用域以及全局变量的问题

    一. JS中的作用域 1.全局变量:函数外声明的变量,称为全部变量 局部变量:函数内部使用var声明的变量,称为局部变量在JS中,只有函数作用域,没有块级作用域!!!也就是说,if/for等有{}的结 ...

  3. C语言中的作用域,链接属性和存储类型

    作用域 当变量在程序的某个部分被声明的时候,他只有在程序的一定渔区才能被访问,编译器可以确认4种不同类型的作用域:文件作用域,函数作用域,代码块作用域和原型作用域 1.代码块作用域:位于一对花括号之间 ...

  4. C语言中简单的for循环和浮点型变量

    浮点型变量:常数中带有小数点的叫做浮点型 以下用for循环写一个摄氏度和华氏度的转换的C程序 [见 http://www.linuxidc.com/Linux/2013-08/88513.htm ] ...

  5. 变量、变量作用域、常量final、变量的命名规范

    变量 变量是什么:就是可以变化的量! Java是一种强类型语言,每个变量都必须声明其类型. Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域. 注意事项: 每个变量都有类型,类 ...

  6. C语言中的静态局部变量

    代码: 0x601070 0x7ffcf44243fc 0x60106c 0x60106c 0x60106c [hu@localhost test]$ cat test.cpp #include &l ...

  7. C语言中结构体定义实际上相当于变量入栈

    struct context { int edi; int esi; int ebx; int ebp; int eip;}; 对应的入栈顺序是 pushl %esp pushl %eip pushl ...

  8. C语言中以文本方式读写文件时换行符转换的注意事项

    我们知道在UNIX下是没有回车符(\r)的,只有换行符(\n),而C语言诞生于UNIX(Linux即面向开源的UNIX,Mac OS也是UNIX发展而来的,而Windows是从MS-DOS发展而来,与 ...

  9. C 语言中包含的标准头文件(24个)

    <assert.h><complex.h><ctype.h><errno.h><fenv.h><float.h><intt ...

随机推荐

  1. 掩码计算工具netmask

    掩码计算工具netmask   在网络扫描和防火墙配置中,经常需要计算IP地址范围和对应的掩码.为了简化这个过程,Kali Linux预置了一个掩码计算工具netmask.该工具不仅可以根据IP地址范 ...

  2. 安装ffmpeg

    安装2个源 centos7.2 1.yum install -y epel-release 2.rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x8 ...

  3. 深入理解yield

    yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法. 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: 1 2 3 def ad ...

  4. 【BZOJ 3470】3470: Freda’s Walk 期望

    3470: Freda’s Walk Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 42  Solved: 22 Description 雨后的Poet ...

  5. Codeforces Round #494 (Div 3) (A~E)

    目录 Codeforces 1003 A.Polycarp's Pockets B.Binary String Constructing C.Intense Heat D.Coins and Quer ...

  6. 【二分答案】Google Code Jam Round 1A 2018

    题意:有R个机器人,去买B件商品,有C个收银员,每个收银员有能处理的商品数量上限mi,处理单件商品所需的时间si,以及最后的装袋时间pi. 每个收银员最多只能对应一个机器人,每个机器人也最多只能对应一 ...

  7. mysqlslap 一个MySQL数据库压力测试工具

    在Xen/KVM虚拟化中,一般来说CPU.内存.网络I/O的虚拟化效率都非常高了,而磁盘I/O虚拟化效率较低,从而磁盘可能会是瓶颈.一般来说,数据库对磁盘I/O要求比较高的应用,可以衡量一下在客户机中 ...

  8. 长城小主机GW1等型号进BIOS的设置方法

    主板型号 1.进BIOS办法 2.BIOS下设置U盘启动 3.主板设置上电启动 4.主要是否具有快速U盘启动功能 5.定时开机设置 945GMS Ctrl+Alt+F1(注意:自检响铃后,再按) 在B ...

  9. .net 基于Jenkins的自动构建系统开发

    先让我给描述一下怎么叫一个自动构建或者说是持续集成 : 就拿一个B/S系统的合作开发来说,在用SVN版本控制的情况下,每个人完成自己代码的编写,阶段性提交代码,然后测试-修改,最后到所有代码完工,进行 ...

  10. ASP.NET Web API教程 分页查询

    首先增加支持分页的API方法 public IEnumerable<UserInfo> GetUserInfos(int pageindex, int size)         {    ...