0.前言

这个系列基本上是一月一更到两月一更

今天写一篇关于static的,内含大量干货,做好准备

1.基础知识的回顾

1.1.内存的种类

一般来说,我们之前已经讲过的变量(或者说是内存)可以大体分为这样几种:

  • 全局变量
  • 局部变量,也称为自动变量
  • 使用malloc分配的区域
  • 常量、字符串字面量

这里回顾一下,在C++中,使用const声明的常量是不可改变的,也就是在编译期就确定下来了。因此,即使使用指针更改也不会实际修改到它的值。对于全局变量,const出的值和字符串字面量(即使用""括起来的字符串),存在常量区,强制改变会使得程序异常退出。

1.2.作用域和生命周期

对于全局变量,它由始至终都是存在的,作用域是全部。

局部变量的作用域和声明周期仅存在一个函数中,当函数返回,它就会从栈中销毁。

使用malloc分配的内存区域,它的生命周期一直到调用free为止。

对于字符串字面量和常量,它的作用域和声明周期与全局变量和局部变量类似。

2.static的相关用法

2.1.静态变量的定义

我们把使用static修饰的变量和全局变量统称为静态变量。

静态变量,顾名思义,就是可以贯穿整个程序运行的时间内的变量。

2.2.static的地址

我们来写一段代码,进行一个实验:

#include<iostream>
#include<windows.h>
using namespace std;
int a;//全局变量
static int b;//全局static变量
void f(void){
static int c;//定义在函数内的static变量
printf("c..%p\n",&c);
}
int main(){
printf("a..%p\n",&a);
printf("b..%p\n",&b);
f();
return 0;
}

(注:今天我换了一台电脑进行编辑,使用的是codeblocks来编辑,编译器我设置的是VC)

输出的结果如下

可以看到,static修饰的变量,与全局变量的地址是接近的,可以证明它是在全局存储区。

2.3.函数体内的static

还是以例子来说明,这样比较好理解。假如我们写一个将数字转为字符串的函数:

#include<iostream>
#include<windows.h>
using namespace std;
char *toint(int x){
char s[1000];
sprintf(s,"%d",x);
return s;
}
int main(){
char s[1000],t[1000];
strcpy(s,toint(8));
strcpy(t,toint(10));
printf("%s\n%s\n",s,t);
return 0;
}

使用sprintf函数,进行字符串间的转换。

这段代码,乍一看似乎没有问题,而且在我的环境还可以正常运行:(部分环境会Segmentation Fault,就更加能说明这个问题)

但是我们仔细看看,画面下方报出了一行警告:

(看我选中的一条,上面一条似乎是环境没有配置到位,先不管了)

这是因为,其中的s数组是局部变量,或者说是自动变量,保存在栈中,在函数返回之后,这个地址就不能再使用了,因为这个数组已经销毁了,s地址所在的地方是“无人区”,访问时就有可能访问到不该访问的数据,进而出错。

对于这一类的问题,解决方法有使用malloc和new来分配内存,这样可以在free之前多次使用:

char *toint(int x){
char *s=new char [1000];
sprintf(s,"%d",x);
return s;
}

这一次没有报错。

事实上,还可以使用静态变量来解决(不过静态变量主要的用途不在这里),这样这个内存就不会在返回的时候被释放。

char *toint(int x){
static char s[1000];
sprintf(s,"%d",x);
return s;
}

同样没有报错。

3.static的更多特性与用途

3.1.在函数退出后,static变量的值保持不变

#include<iostream>
#include<windows.h>
using namespace std;
void f(){
static int Count;
printf("%d\n",Count);
Count++;
}
int main(){
for(int i=0;i<10;i++){
f();
}
}

由于static的变量一直在同一个存储区,因此可以发现,退出函数时,static变量的值保持不变,输出结果为:

3.2.多文件中的使用

static的变量,只能在当前的文件内进行访问。

//a.cpp
static int x; int main(){
x=100;
cout<<x<<endl;
f();
} //b.cpp
extern int x;
void f(){
cout<<x<<endl;
}

在b.cpp中,无法访问a.cpp中的x变量,因为x是使用static修饰的(即使使用了extern进行声明)

包括函数也可以使用static进行修饰:

static int f();

关于更多的内容,敬请期待:

【原创】浅谈指针(十三)关于static(下)

(预计5月发布)

【原创】浅谈指针(十二)关于static(上)的更多相关文章

  1. 转载 浅谈C/C++中的static和extern关键字

    浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T   static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...

  2. [原创]浅谈如何使用gcc开发NT核心驱动程序

    原文链接:[原创]浅谈如何使用gcc开发NT核心驱动程序 一谈到在 Win NT 下开发核心驱动程序,可能不少人首先都会想到微软“正统”的VC来.诚然,用VC 配合 WINDDK 的确工作的不错,但或 ...

  3. [原创]浅谈移动App安全测试

    [原创]浅谈移动App安全测试 移动互联网很火,就像当年互联网兴起一样,这几天和朋友在沟通交流,谈到一个话题,你们做金融App钱放在你们哪边安全不?会不会你们做的移动App不安全,让人盗了里面的资金, ...

  4. 浅谈Kotlin(二):基本类型、基本语法、代码风格

    浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型.基本语法.代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 通过上面的文章,在A ...

  5. [原创]浅谈移动互联网App兼容性测试

    [原创]浅谈移动互联网App兼容性测试 今天要谈的话题,估计各位测试都有感受,移动互联网App兼容性测试,我们到底测试覆盖如何去挑选机型?具体移动App兼容性测试如何开展?是不是应引进像testin这 ...

  6. [原创]浅谈IT人如何做理财规划

    [原创]浅谈IT人如何做理财规划 鱼哥博客上多数写的是技术和管理相关,但很少有理财等话题,今天抽空来谈谈IT人如何做理财规划,如果要想学习理财,我想很有名的“标准普尔家庭资产象限图”上值得每个学习和理 ...

  7. [原创]浅谈Web UI自动化测试

    [原创]浅谈Web UI自动化测试 Web UI自动化测试相信大家都不陌生,今天来谈谈这个,我最早接触自动化测试时大约是在2004年,2006年当时在腾讯财付通算是开始正式接触自动化测试,之所以是正式 ...

  8. 浅谈Java代理二:Cglib动态代理-MethodInterceptor

    浅谈Java代理二:Cglib动态代理-MethodInterceptor CGLib动态代理特点: 使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生 ...

  9. [原创] 浅谈ETL系统架构如何测试?

    [原创] 浅谈ETL系统架构如何测试? 来新公司已入职3个月时间,由于公司所处于互联网基金行业,基金天然固有特点,基金业务复杂,基金数据信息众多,基金经理众多等,所以大家可想一下,基民要想赚钱真不容易 ...

随机推荐

  1. Hadoop-全分布式配置

    目录 一.配置基础环境 1.配置网络信息 2.配置主机名 3.主机名与IP的映射关系 4.测试互通性 二.关闭防火墙和SELinux 1.关闭防火墙 2.关闭SELinux 三.安装 Hadoop 1 ...

  2. P2P图书馆实践:让知识更好的传播

    人才是每个公司最重要的资产,而人的成长自然就成了最重要的事.苏轼曾经说过:"腹有诗书气自华,代码万行零缺陷",阅读对人成长的影响是巨大的.相信不同的团队都有着自己打造学习氛围.技术 ...

  3. redis主从复制和哨兵机制

    redis主从复制和哨兵机制 技术标签: redis 1.redis主从复制(master/slave模式) 主数据库可以进行读写操作,当写操作导致数据发生变化时会自动将数据同步给从数据库.而一般情况 ...

  4. abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

    abstract的method 不可以是static的,因为抽象的方法是要被子类实现的,而static与子类扯不上关系! native方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类 ...

  5. Java 线程池中 submit() 和 execute()方法有什么区别?

    两个方法都可以向线程池提交任务,execute()方法的返回类型是 void,它定义在 Executor 接口中. 而 submit()方法可以返回持有计算结果的 Future 对象,它定义在 Exe ...

  6. Mybatis 的一级、二级缓存?

    1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 C ...

  7. Redis 集群方案什么情况下会导致整个集群不可用?

    有 A,B,C 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了, 那么整个集群就会以为缺少 5501-11000 这个范围的槽而不可用.

  8. 什么是 UML?

    UML 是统一建模语言(Unified Modeling Language)的缩写,它发表于 1997 年,综合了当时已经存在的面向对象的建模语言.方法和过程,是一个支持模型 化和软件系统开发的图形化 ...

  9. 学习移动机器人SLAM、路径规划必看的几本书

    作者:小白学移动机器人链接:https://zhuanlan.zhihu.com/p/168027225来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 声明:推荐正版图 ...

  10. ps基础总结

    1.复制图层:首先选中移动工具(V),鼠标右键选中需要复制的图层(快捷方式:上面勾选自动选择),接着一只手按住Alt键,另一只手点击鼠标左键(不松开),往左往右移动即可.若是对多个图层起作用,就可将需 ...