C/C++ static、extern
一、static本质作用
与static相对的关键字是auto,两者是一对。我们一般声明变量,如:int a,其实都是auto int a,只是auto省略了而已,但是static不能省略。要理解static,最好先理解auto。auto的含义是由程序自动控制变量的生存周期,通常是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static则不同,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是按照变量自己的生命周期。
二、static用法
1.局部变量
如:void func()
{
int a;
static int b;
}
就算函数结束了,b的值也能够一直保持。每一次调用该函数,变量a都是新的,因为它是在进入函数体的时候被分配,退出函数体的时候被释放,所以多个线程调用该函数,都会拥有各自独立的变量a,因为它总是要被重新分配的;而变量b不管你是否使用该函数,在程序初始化时就被分配的了,或者在第一次执行到它的声明的时候分配(不同的编译器可能不同),所以多个线程调用该函数的时候,总是访问同一个变量b,这也是在多线程编程中必须注意的!
一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。
2.类的静态数据成员
class A
{
private:
static int s_value;
};
类的静态成员必须初始化才能使用,因为它是在程序初始化的时候分配的,所以必须有初始化,类中只是声明,在cpp中才是初始化,静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:
int A::s_value = 0;//<数据类型><类名>::<静态数据成员名>=<值>,注意,这里没有static的修饰!使用静态成员时,可以通过双冒号(即<类名>::<静态成员名>,也可以通过对象调用)。类的静态成员是该类所有实例的共用成员,也就是在该类的范畴内是个全局变量,也可以理解为是一个名为A::s_value的全局变量,只不过它是带有类安全属性的。道理很简单,因为它是在程序初始化的时候分配的,所以只分配一次,所以就是共用的。
3.类的静态成员函数
class A
{
private:
void init();
static void output();
};
void main()
{
A::init(); //A::init();会出错,因为不能通过类名来调用类的非静态成员函数。
A::output();
}
void main()
{
A pt;
pt.init();
pt.output();
} //编译通过,因为类的对象可以使用静态成员函数和非静态成员函数。
静态成员函数和静态数据成员一样,它们都属于类的静态成员,不是对象成员。因此,对静态成员的引用不需要用对象名,当然,通过对象来使用也可以。在静态成员函数的实现中不能直接引用类的非静态成员,可以引用类中的静态成员。如果静态成员函数中要引用非静态成员时,可通过对象来引用。因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以调用就会出错,就好比没有声明一个变量却提前使用它一样。
实现的时候也不需要static的修饰,因为static是声明性关键字;类的静态函数是在该类的范畴内的全局函数,实际上,它就是增加了类的访问权限的全局函数:void A::output();
注意:静态成员函数可以继承和覆盖,但无法是虚函数;在类的非静态成员函数中可以使用类的静态成员。
4.文件内全局变量
若在cpp中有,static int g_value = 0;
这个变量的含义是在该cpp内有效,其他的cpp文件不能访问这个变量;如果有两个cpp文件声明了同名的全局静态变量,那么他们实际上是独立的两个变量;如果不使用static声明全局变量:int g_value=0;那么将无法保证这个变量不被别的cpp共享,也无法保证一定能被别的cpp共享,看有没有extern。
5.普通函数
即静态函数,它只能在声明它的文件当中可见,不能被其它文件使用。
三、extern
extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,可能是在别的文件,也可能是在本文件当前位置的后面,但是要在此处引用”。在这里要注意extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。其实要调用其它文件中的函数和变量,只需把该文件用#include包含进来即可,为啥要用extern?因为用extern会加速程序的编译过程,这样能节省时间。
1.cpp文件中
file1.cpp
int a=1;
file2.cpp
#include<stdio.h>
extern int a;
int main(void)
{
printf("%d\",a);
return 0;
}
这样,file2就可以用file1中的int a了,但是如果在file1中把int a=1改为static int a=1;那么在file2是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。
2.指示调用规范
在C++中extern还有另外一种作用,用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题。
C/C++ static、extern的更多相关文章
- 如何正确使用const、static、extern
转自:http://www.jianshu.com/p/2fd58ed2cf55 前言 本篇文章主要介绍在开发中怎么使用const.static.extern关键字. 一.const 与宏的区别: c ...
- 88、const、static、extern介绍
一.const与宏的区别 const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编译(编译之前处理)const是编译阶段. 编译检 ...
- oc温习八:static、extern、const 的了解
参考文章:http://www.cocoachina.com/ios/20161110/18035.html 1.const 这个单词翻译成中文是“常量”的意思.在程序中我们知道“常量”的值是不能变的 ...
- 【VS开发】static、extern分析总结
引用请注明出处:http://blog.csdn.net/int64ago/article/details/7396325 对于写了很多小程序的人,可能static和extern都用的很少,因为sta ...
- C语言中volatile、register、const、static、extern、 auto关键字的作用
一.volatile详解 volatile的本意是"易变的" 因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据.当要求使用volat ...
- 关键字static、extern、volatile、详解及举例
一.预备知识 1. 什么是局部变量?什么是全局变量? 所谓局部变量,就是指在函数内部定义的变量的,只在该函数范围内有效. 全局变量是指,在函数外部定义的变量为外部变量,即全局变量.它 ...
- const、static、extern三个关键字
默认情况下,C语言的全局变量是全世界都可以访问的,也就是全局变量可以跨文件访问. extern可以引用全局变量 例如,如果有一个全局变量int money = 100;extern int money ...
- c语言中static、extern、void的重载
static: 1.在函数内部,表示该变量的值在各个调用间一直保持延续性: 2.在函数这一级,表示该函数只对本文件可见. extern: 1.用于函数定义,表示全局可见(属于冗余的): ...
- OC中使用 static 、 extern、 const使用
static static用于定义静态变量,静态变量只会被初始化一次,并且直到程序销毁时才会释放 static NSString *str = @"asdfa"; const co ...
随机推荐
- iOS8使用TouchID
iOS8新增了LocalAuthentication框架,用于TouchID的授权使用.亲測,眼下须要用户的设备支持指纹识别并已设置锁屏,并且实际測试过程中反馈比較慢.不能直接跟第三方账号passwo ...
- centos部署jenkins
1. 实验环境: 操作系统: CentOS Linux release 7.2.1511 (Core) 软件版本: jdk-8u60-linux-x64 apache-tomcat-9.0. ...
- Mac OS 10.10.3下Apache + mod_wsgi配置【一】
[一] 首先,MAC是自带Apache的,在/private/etc/apache2路径下,能够使用apachectl -v查看版本号.我的版本号例如以下: Server version: Apach ...
- windows7 配置 python开发环境
1.安装python2.7 官网下载,安装,配置环境变量 path,命令行 执行python 2.easy_install 安装 win7 64位必须使用ez_setup.py进行安装. 方法 ...
- [计算机故障]笔记本无法启动,开机启动出现“Operating System Not Found”无法进系统
背景介绍:同事的一台索尼的笔记本,安装XP.开机启动出现“Operating System Not Found”无法进系统 诊断: 初步判断硬盘故障.但听声音,没有异响. 开机按F2进入BIOS设置. ...
- android:模拟水波效果的自己定义View
Github地址:https://github.com/nuptboyzhb/WaterWaveView 欢迎Fork.欢迎Star 1.先看效果 watermark/2/text/aHR0cDovL ...
- Spring Boot Controller
接上篇文章.HelloWorld程序中我们已经创建了一个HellController,里面包括了响应JSON的方法.本文针对Controller再做一下解说. 回想上篇文章,我们在Controller ...
- VMware14秘钥
VMware虚拟机已升级至14版本,之前的12版本的秘钥已经无法使用,在此分享一下VMware Workstation 14永久激活密钥: CG54H-D8D0H-H8DHY-C6X7X-N2KG6 ...
- MATLAB——matlab特殊符号表【转载】
链接来源: matlab特殊符号表 http://blog.sina.com.cn/s/blog_4a09187801014xg9.html Character Sequence Symbol Cha ...
- ubuntu14安装docker-ce
先卸载旧的docker sudo apt-get remove docker docker-engine docker.io docker-ce 通过HTTPS使用存储库(repository) su ...