google了近三页的关于C语言中static的内容,发现可用的信息非常少,要么长篇大论不知所云要么在关键之处几个字略过,对于想挖掘底层原理的刚開始学习的人来说參考性不是非常大。所以,我这篇博文博採众家之长,把互联网上的资料整合归类,并亲手编敲代码验证之。

C语言代码是以文件为单位来组织的,在一个源程序的全部源文件里,一个外部变量(注意不是局部变量)或者函数仅仅能在一个源程序中定义一次,假设有反复定义的话编译器就会报错。伴随着不同源文件变量和函数之间的相互引用以及相互独立的关系,产生了extern和statickeyword。

以下,具体分析一下statickeyword在编敲代码时有的三大类使用方法:

一,static全局变量

我们知道,一个进程在内存中的布局如图1所看到的:

当中.text段保存进程所运行的程序二进制文件,.data段保存进程全部的已初始化的全局变量,.bss段保存进程未初始化的全局变量(其它段中还有非常多乱七八糟的段,暂且不表)。在进程的整个生命周期中,.data段和.bss段内的数据时跟整个进程同生共死的,也就是在进程结束之后这些数据才会寿终就寝。

当一个进程的全局变量被声明为static之后,它的中文名叫静态全局变量。静态全局变量和其它的全局变量的存储地点并没有差别,都是在.data段(已初始化)或者.bss段(未初始化)内,可是它仅仅在定义它的源文件内有效,其它源文件无法訪问它。所以,普通全局变量穿上static外衣后,它就变成了新娘,已心有所属,仅仅能被定义它的源文件(新郎)中的变量或函数訪问。

下面是一些演示样例程序

file1.h例如以下:

#include <stdio.h>void printStr();

我们在file1.c中定义一个静态全局变量hello, 供file1.c中的函数printStr訪问.

#include "file1.h"static char* hello = "hello cobing!";void printStr()
{printf("%s\n", hello);
}

file2.c是我们的主程序所在文件,file2.c中假设引用hello会编译出错

#include "file1.h"int main()
{printStr();printf("%s\n", hello);return 0;
}

报错例如以下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
file2.c: In function ‘main’:
file2.c:6: 错误:‘hello’ 未声明 (在此函数内第一次使用)
file2.c:6: 错误:(即使在一个函数内多次出现,每一个未声明的标识符在其
file2.c:6: 错误:所在的函数内仅仅报告一次。)

假设我们将file2.c改为以下的形式:

#include "file1.h"int main()
{printStr();return 0;
}

则会顺利编译连接。

执行程序后的结果例如以下:
[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
[liujx@server235 static]$ ./file2
hello cobing!

上面的样例中,file1.c中的hello就是一个静态全局变量,它能够被同一文件里的printStr调用,可是不能被不同源文件里的file2.c调用。

二,static局部变量

普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调用这个局部变量在栈上的位置都不一定同样。局部变量也能够在堆上动态分配,可是记得使用完这个堆空间后要释放之。

static局部变量中文名叫静态局部变量。它与普通的局部变量比起来有例如以下几个差别:

1)位置:静态局部变量被编译器放在全局存储区.data(注意:不在.bss段内,原因见3)),所以它尽管是局部的,可是在程序的整个生命周期中存在。

2)訪问权限:静态局部变量仅仅能被其作用域内的变量或函数訪问。也就是说尽管它会在程序的整个生命周期中存在,因为它是static的,它不能被其它的函数和源文件訪问。

3)值:静态局部变量假设没有被用户初始化,则会被编译器自己主动赋值为0,以后每次调用静态局部变量的时候都用上次调用后的值。这个比較好理解,每次函数调用静态局部变量的时候都改动它然后离开,下次读的时候从全局存储区读出的静态局部变量就是上次改动后的值。
下面是一些演示样例程序:

file1.h的内容和上例中的同样,file1.c的内容例如以下:

#include "file1.h"void printStr()
{int normal = 0;static int stat = 0;  //this is a static local varprintf("normal = %d ---- stat = %d\n",normal, stat);normal++;stat++;
}

为了便于比較,我定义了两个变量:普通局部变量normal和静态局部变量stat,它们都被赋予初值0;

file2.c中调用file1.h:

#include "file1.h"int main()
{printStr();printStr();printStr();printStr();printf("call stat in main: %d\n",stat);return 0;
}

这个调用会报错,由于file2.c中引用了file1.c中的静态局部变量stat,例如以下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
file2.c: In function ‘main’:
file2.c:9: 错误:‘stat’ 未声明 (在此函数内第一次使用)
file2.c:9: 错误:(即使在一个函数内多次出现,每一个未声明的标识符在其
file2.c:9: 错误:所在的函数内仅仅报告一次。)

编译器说stat未声明,这是由于它看不到file1.c中的stat,以下注掉这一行:

#include "file1.h"int main()
{printStr();printStr();printStr();printStr();
//  printf("call stat in main: %d\n",stat);return 0;
}

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
[liujx@server235 static]$ ./file2
normal = 0 ---- stat = 0
normal = 0 ---- stat = 1
normal = 0 ---- stat = 2
normal = 0 ---- stat = 3
执行如上所看到的。能够看出,函数每次被调用,普通局部变量都是又一次分配,而静态局部变量保持上次调用的值不变。

须要注意的是因为static局部变量的这样的特性,使得含静态局部变量的函数变得不可重入,即每次调用可能会产生不同的结果。这在多线程编程时可能会成为一种隐患。须要多加注意。

三,static函数
              相信大家还记得C++面向对象编程中的private函数,私有函数仅仅有该类的成员变量或成员函数能够訪问。在C语言中,也有“private函数”,它就是接下来要说的static函数,完毕面向对象编程中private函数的功能。

当你的程序中有非常多个源文件的时候,你肯定会让某个源文件仅仅提供一些外界须要的接口,其它的函数可能是为了实现这些接口而编写,这些其它的函数你可能并不希望被外界(非本源文件)所看到,这时候就能够用static修饰这些“其它的函数”。

所以static函数的作用域是本源文件,把它想象为面向对象中的private函数就能够了。

以下是一些演示样例:

file1.h例如以下:

#include <stdio.h>static int called();
void printStr();

file1.c例如以下:

#include "file1.h"static int called()
{return 6;
}
void printStr()
{int returnVal;returnVal = called();printf("returnVal=%d\n",returnVal);
}

file2.c中调用file1.h中声明的两个函数,此处我们有益调用called():

#include "file1.h"int main()
{int val;val = called();printStr();return 0;
}

编译时会报错:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
file1.h:3: 警告:‘called’ 使用过但从没有定义
/tmp/ccyLuBZU.o: In function `main':
file2.c:(.text+0x12): undefined reference to `called'
collect2: ld 返回 1
由于引用了file1.h中的static函数,所以file2.c中提示找不到这个函数:undefined reference to 'called'

以下改动file2.c:

#include "file1.h"int main()
{printStr();return 0;
}

编译执行:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
[liujx@server235 static]$ ./file2
returnVal=6

static函数能够非常好地解决不同原文件里函数同名的问题,由于一个源文件对于其它源文件里的static函数是不可见的。

有疏漏的地方望各位多多不吝赐教~~

C语言中的static 具体分析相关推荐

  1. C语言中的static 详细分析

    google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大论不知所云要么在关键之处几个字略过,对于想挖掘底层原理的初学者来说参考性不是很大.所以,我这篇博文博采众家之长,把互 ...

  2. C语言中的static 详细分析 2014-10-11 15:15 143人阅读 评论(0) 收藏...

    转自:http://blog.csdn.net/keyeagle/article/details/6708077 看到这篇文章针对C语言的static关键字解释的比较好,这里转载过来.谢谢原作者分享. ...

  3. c语言中的static变量和static函数

    在C语言中,static的字面意思很容易把我们导入歧途,其实它的修饰变量作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函 ...

  4. C/C++中Static的作用详述 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。

    C/C++中Static的作用详述 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加s ...

  5. 【C语言进阶深度学习记录】九 C语言中const的详细分析

    文章目录 1 const的分析 2 const本质的分析实验 2.1 代码案例分析 3 const修饰函数参数和返回值时的情况 3.1 代码案例分析 4 总结 1 const的分析 不管是C语言还是C ...

  6. C语言中的static

    C程序一直由下列部分组成:       1)正文段--CPU执行的机器指令部分:一个程序只有一个副本:只读,防止程序由于意外事故而修改自身指令:       2)初始化数据段(数据段)--在程序中所有 ...

  7. c语言中的static inline

    inline的作用仅仅是建议编译器做内联开展处理,而不是强制. 内联函数(inline)可以减少CPU的系统开销,并且程序的整体速度将加快,但当内联函数很大时,会有相反的作用,因此一般比较小的函数才使 ...

  8. C语言中的static的作用~

    static的三个作用 1.修饰局部变量 2.修饰全局变量 3.修饰函数 要想更好地理解static的作用,我们有必要介绍一下以下三个概念: 内存的栈区.堆区.静态区 这就内存中的栈区.堆区.静态区里 ...

  9. C语言中的static函数

    C语言是以文件文件为单位组织的,在一个源程序的所有文件中,一个外部变量和函数只能在源程序中定义一次.由于不同文件中的不同函数和变量很多时候都会相互引用,因此出现了static和extern关键字.这里 ...

最新文章

  1. 什么是7层负载均衡?
  2. GraphQL:和EntityFramework更配哦
  3. 【lora模块技术无线数传电台】E90-DTU产品高防护等级的体现
  4. 李春雷 | 夜宿棚花村
  5. [js]js设计模式-构造函数模式
  6. Tomcat 系统架构与设计模式之设计模式篇
  7. 单层感知机实现或运算
  8. php utc时间_datetime - 以PHP格式获取UTC时间
  9. 判断 360浏览器极速 / 兼容模式
  10. 举例说明数据库一、二、三及BCNF范式
  11. 【CV】细粒度图像分割 (FGIS)
  12. 改进YOLOv7系列:21.添加ShuffleAttention注意力机制
  13. N沟道的Vgs是正的,P沟道的Vgs是负的
  14. 涨价不再“嘘声”一片,“爱优腾”集体“想开了”?
  15. 200万年薪,西交大2位计算机博士入选华为天才少年
  16. Transformer模型技术长文
  17. 【pytest】使用 mark 标记及运行测试用例,注册、管理 mark 标记
  18. 如何用 js 获取虚拟键盘高度?(适用所有平台)
  19. PHONEGAP BUILD
  20. Telegram桌面端(tdesktop)编译方法

热门文章

  1. Java好学吗?Java能做什么?如何快速入门Java?
  2. 基于OpenCV的计算机视觉入门(4)线段和形状的绘制
  3. linux Centos下mysql安装
  4. 解决问题:Appium WebView 跳转页面后无法定位元素
  5. 理解 TCP(二):报文结构 1
  6. iOS开发 - OC - 苹果为大家提供的后台:CloudKit 的简单使用
  7. 炒冷饭系列:设计模式 单例模式
  8. GoogLeNetV1,V2,V3
  9. 级数形式套级数的敛散性判断
  10. Ubuntu下自定义调整CPU工作频率(用于省电或提高性能都好用)