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 var
printf("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 详细分析

    转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...

  2. 【转载】C语言中的static 详细分析

    原blog地址:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少, ...

  3. 转:C语言中的static变量和C++静态数据成员(static member)

    转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序 ...

  4. C语言中的static的作用?

    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)第一个作用:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话 ...

  5. C语言中的static关键字

    C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重复定义的话编译器就会报错.伴随着不同源文件变量和函数之间的相互 ...

  6. C语言中的static和extern

    c语言中,全局变量是一个非常重要的概念.全局变量定义在函数外,可以被所有的函数共同使用. #include <iostream> ; void display() { printf(&qu ...

  7. C语言中:static与extern对变量和函数的作用

    1.两者对全局变量 static对全局变量,表示定义一个内部变量 extern对全局变量,表示声明一个外部变量 说明: 1.内部变量:定义的变量只能在本文件中访问,不能被其他文件访问. 2.不同文件中 ...

  8. [整理]C语言中的static静态对象

    1.说明外部对象(静态外部变量和静态函数)    (1)static 用于说明外部变量或函数,使该对象的作用域限定为被编译原文件的剩余部分,即从对象说明开始到所在源文件的结束部分:    (2)被st ...

  9. C语言中,static关键字作用

    static修饰变量 1 在块中使用static修饰变量 它具有静态存储持续时间.块范围和无链接. 即作用域只能在块中,无法被块外的程序调用:变量在程序加载时创建,在程序终止时结束. 它只在编译时初始 ...

随机推荐

  1. java thread reuse(good)

    I have always read that creating threads is expensive. I also know that you cannot rerun a thread. I ...

  2. 事件总线帧---Otto

    我们如果这样一种业务场景.如今在做一款及时聊天应用,我们在聊天页面进行收发信息.同一时候也要实时更新前一页面的聊天记录,这时我们该怎样去实现?说说我曾经的实现策略.我使用的是广播接收器BroadCas ...

  3. Android开发技术周报

    Android开发技术周报 原文  http://androidweekly.cn/android-dev-weekly-issue48/ 教程 深入理解Android之Gradle Gradle是当 ...

  4. 外语学习强烈推荐Rosetta Stone

    外语学习强烈推荐Rosetta Stone 外语学习强烈推荐Rosetta Stone

  5. Ubuntu 12.04更新源

    源地址:http://www.cnblogs.com/eastson/archive/2012/08/24/2654163.html 1.首先备份Ubuntu12.04源列表 sudo cp /etc ...

  6. 百度地图API相关点

    百度API接口:http://developer.baidu.com/map/jsdemo.htm#a1_1 百度地图API具体解释之地图标注:http://www.cnblogs.com/jz110 ...

  7. HTML5线性图表 图表数据区域可着色

    这是一款基于Canvas的HTML5图表应用,在图表数据初始化的时候伴随动画效果. 在线演示: 点击演示 源代码下载: 点击下载 核心jQuery代码: var myData = {   labels ...

  8. Ucan23操作系统项目地址

    期间耽误了近半年的时间.在昨天最终完毕了Ucan23OS, 项目托管在GitHub上,地址为: https://github.com/howardking/UCAN23OS 以下为操作系统的执行截图 ...

  9. Cocos2d-x Tiled地图编辑器(一)基本使用

    Tiled地图编辑器支持普通视角地图和45度角地图, 它生成的地图数据文件cocos2d-x完美的支持,Tiled地图编辑器是一个以普通使用为目标地图编辑器,它使用简单而且能够轻松地在不同的游戏引擎中 ...

  10. pygame在安装过程中无法找到videodev.h错误

    首先参考<ubuntu 安装 pygame 非常好玩的东西>.在运行sudo python setup.py时.出现 linux/videodev.h:No such file or di ...