C/C++ auto, static , register , extern 区别

先说几个概念:

1.从变量的生存期来分,可以分为 静态存储方式
动态存储方式

静态存储方式:程序运行期间由系统分配固定的存储空间的方式(全局变量)

动态存储方式:程序运行期间根据需要动态的分配存储空间的方式(1.函数形参,2自动变量,3函数调用时的现场保护盒返回地址)

2.数据存储类别包含四种:auto(自动), static (静态),register(寄存器),
extern (外部)

auto: 关键字auto可以省略,auto不写隐含确定为自动存储类别,属于动态存储方式

static: 有时候希望i函数的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量已经有值(上一次函数调用结束时的值)

例子:

#include "stdafx.h"
#include <iostream>
using namespace std;

int fun(int a)
{
	int b=0;
	static int c=3;
	b++;
	c++;
	return a+b+c;
}
int _tmain(int argc, _TCHAR* argv[])
{
	int a=100;
	for (int i = 0; i < 3; i++)
	{
		cout<<fun(a)<<endl;
	}
	return 0;
}

输出结果:

a的值不变

b每次调用时初值为0,调用后为1

c调用时初值分别为3,调用后位4

------ 4,-------------5

------ 5,-------------6

说明:

1.静态局部变量属于静态存储类别,在静态存储区内分配存储单元

2.对于静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值,以后每次调用函数时不再重现赋初值而只是保留上次函数调用结束时的值。(自动变量赋初值,不是在编译时,而是在函数调用时进行,每次重现调用都重新赋予初值)

3.如果不赋予初值,对于静态局部变量来说,编译时自动赋值0(int型)或空字符(char型);而对于自动变量来说,不赋初值则它是一个不确定的值。

4.虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。

register :如果一些变量使用频繁,可以用关键字register作声明(由于对寄存器的存取速度远高于对内次的存取速度,这样做可以提高执行效率)

说明:

1.只有局部自动变量和形参可以作为寄存器变量,其它如全局变量不行

2.一个计算机中的寄存器数目是有限的,不能定义任意多个寄存器变量。不同的系统允许使用的寄存器个数是不同的,对register变量的处理方法也是不同的,有的系统对register变量当作自动变量处理,分配存储单元,并不真正把它们存放在寄存器中,有的系统只允许将int,char和指针变量定义为寄存器变量。

3.局部变量不能定义为寄存器变量,不能将变量既放在静态存储区,又放到寄存器中,二者只能居其一。对于一个变量只能声明为一种存储类别

4.当今优化编译系统能够识别使用频繁的变量,从而自动将这些变量放在寄存器中,不需要程序设计者指定。因此,实际上用register声明变量是不必要的。

extern :

外部变量:外部变量是在函数的外部定义的变量,它的作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序中的各个函数所引用。编译时将外部变量分配在静态存储区。

用extern来声明外部区域,扩展外部变量的作用域。

1.在一个文件内声明外部变量

如果外部变量不在定义的开头定义,其有效的作用范围只限定于定义处到文件结束。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量做外部变量声明,表示该变量是一个已经定义的外部变量,有了此声明,就可以从声明处起,合法地使用该外部变量。

// CTestProject.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	extern int A,B;
	cout<<"A:"<<A<<endl;
	cout<<"B:"<<B<<endl;
	return 0;
}

int A=5,B=10;

如果没有extern int A,B这句,则会报卫生棉的标识符A,B

当然更好的做法是:外部变量的定义放在引用它的所有函数之前,可以避免函数中添加一个extern关键字

#include "stdafx.h"
#include <iostream>
using namespace std;

int A=5,B=10;
int _tmain(int argc, _TCHAR* argv[])
{
	//extern int A,B;
	cout<<"A:"<<A<<endl;
	cout<<"B:"<<B<<endl;
	return 0;
}

2.在多个文件的程序中声明外部变量

如果程序有多个源文件,在一个文件想引用另一个文件中已定义的外部变量,可以使用extern 扩展作用域。

如:a.c文件 有个变量A,b.c想引用变量A,只需要在文件开头处extern A即可(不能分别在a.c b.c文件中各自定义一个变量A,否则在程序连接时会出现重复定义的错误),在编译和连接时,系统会由此知道A是一个已经在别处定义的外部变量,并将在另外一个文件中定义的外部变量的作用域扩展到本文件,在本文件中可以合法的引用外部变量A

extern既可以扩展外部变量在本文件的作用域,又可以扩展外部变量的作用域从一个文件到另外一个文件,系统的处理规则是:

1,先在本文件中招外部变量的定义,如果找到,就在本文件中扩展作用域;

2,如果找不到,就在连接时从其他文件中找外部变量的定义,如果找到,就将作用域扩展到本文件;

3,如果未找到,就按出错处理

3.静态外部变量(用static 声明外部的变量)

如果在程序设计中希望某些外部变量只限于被本文件引用,而不能被其他文件引用,则可以使用static声明

如:a.c

static int A

void main()

{

...

}

b.c

extern int A;

void fun()

{

....

}

b.c文件中无法使用a.c中的全局变量A

时间: 2024-11-09 20:29:24

C/C++ auto, static , register , extern 区别的相关文章

[C/C++] extern关键字详解以及与static、const区别

extern用法详解: 1. 声明外部实体 声明外部全局变量或对象,一般用于头文件中,表示在其它编译单元内定义的变量,链接时进行外部链接,如: extern int ivalue; 此时的extern是必须的,省略了extern编译器将视为定义而不是声明,一般地在源代码中定义变量并进行初始化,在头文件中使用extern声明变量. 类似地用于声明外部全局函数,表示该函数在其它编译单元中定义,如: extern void func( void ); 此时的extern可以省略. 2. 声明函数的编译

static和extern

以下内容来自:http://blog.csdn.net/cclive1601/article/details/8063505 一些基本概念: 1. 编译单元(模块):    在IDE开发工具大行其道的今天,对于编译的一些概念很多人已经不再清楚了,很多程序员最怕的就是处理连接错误(LINK ERROR), 因为它不像编译错误那样可以给出你程序错误的具体位置,你常常对这种错误感到懊恼,但是如果你经常使用gcc,makefile等工具在linux或者嵌 入式下做开发工作的话,那么你可能非常的理解编译与

auto和register关键字

关键字概述 很多朋友看到这儿可能会有疑问,往往其它讲C语言的书籍都是从HelloWorld,数据类型开始C语言学习的,为什么我们要从C语言的关键字开始呢?关于这点,我有两点需要说明: 本章节面向的读者对象是有一定的C语言基础知识的朋友(至少应该学习过大学里的C语言程序设计等类似的课程) 本章节结合了作者多年嵌入式工作.研究.教学经验而作,由计算机底层硬件到上层软件设计融会贯通,中间有大量的深入浅出的示例 在我对C语言进行培训的时候,往往就是从C语言的关键字入手,因为C语言的关键字蕴含了C语言的全

18-C语言static和extern关键字1-对函数的作用

一.extern与函数 在第三讲和第四讲中,我提到过一句话:如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.obj中定义的一个函数.将这些相关联的目标文件链接在一起后才能生成可执行文件. 先来理解2个概念: 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数. 内部函数:如果在当前文件中定义的函数不允许其他文件访问

c语言预处理指令、typedef、static和extern相关介绍

一:typedef 作用:可以给一个已经存在的数据类型取一个别名 格式:typedef 原数据类型  新类型   例如:typedef   int  INT; 预处理指令#define 也可以给数据类型取别用用法:  #define  INT  int; //1.用在基本数据类型上 int a = 10; typedef int TNT; typedef char CHAR; CHAR c='A'; //65 TNT b = 100; //2.给数组起别名 char ch[5]; typedef

15-static和extern关键字1-对函数的作用

一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.obj中定义的一个函数.将这些相关联的目标文件链接在一起后才能生成可执行文件. 先来理解2个概念: 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数. 内部函数:如果在当前文件中定义的函数不允许其他文件访问.调用,只能在内部使用,就称为内部函

static 和extern关键字

static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明.本文主要介绍C/C++中的static和extern关键字. static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern, "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方

黑马程序员————C语言(预处理指令、static与extern、typedef)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 第一讲  预处理指令 预处理指令的概述 C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释,比如之前使用的#include文件包含指令,产生一个新的源程序,这个过程称为编译预处理,之后再进行通常的编译 为了区分预处理指令和一般的C语句,所有预处理指令都以符号"#"开头,并且结尾不用分号 预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到文件尾.习惯上我们尽

【黑马程序员】————static和extern关键字1-对函数的作用

一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.obj中定义的一个函数.将这些相关联的目标文件链接在一起后才能生成可执行文件. 先来理解2个概念: 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数. 内部函数:如果在当前文件中定义的函数不允许其他文件访问.调用,只能在内部使用,就称为内部函