【原创】浅谈指针(十二)关于static(上)


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..%pn",&c); } int main(){     printf("a..%pn",&a);     printf("b..%pn",&b);     f();     return 0; }  

(注:今天我换了一台电脑进行编辑,使用的是codeblocks来编辑,编译器我设置的是VC)
输出的结果如下
【原创】浅谈指针(十二)关于static(上)

可以看到,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("%sn%sn",s,t);     return 0; }  

使用sprintf函数,进行字符串间的转换。
这段代码,乍一看似乎没有问题,而且在我的环境还可以正常运行:(部分环境会Segmentation Fault,就更加能说明这个问题)
【原创】浅谈指针(十二)关于static(上)

但是我们仔细看看,画面下方报出了一行警告:
【原创】浅谈指针(十二)关于static(上)

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

这是因为,其中的s数组是局部变量,或者说是自动变量,保存在栈中,在函数返回之后,这个地址就不能再使用了,因为这个数组已经销毁了,s地址所在的地方是“无人区”,访问时就有可能访问到不该访问的数据,进而出错。
【原创】浅谈指针(十二)关于static(上)

对于这一类的问题,解决方法有使用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("%dn",Count);     Count++; } int main(){     for(int i=0;i<10;i++){         f();     } }  

由于static的变量一直在同一个存储区,因此可以发现,退出函数时,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月发布)

发表评论

相关文章