C语言中的static 具体分析
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 具体分析的更多相关文章
- C语言中的static 详细分析
转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...
- 【转载】C语言中的static 详细分析
原blog地址:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少, ...
- 转:C语言中的static变量和C++静态数据成员(static member)
转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量 a.静态局部变量在函数内定义,生存期为整个程序 ...
- C语言中的static的作用?
在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)第一个作用:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话 ...
- C语言中的static关键字
C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重复定义的话编译器就会报错.伴随着不同源文件变量和函数之间的相互 ...
- C语言中的static和extern
c语言中,全局变量是一个非常重要的概念.全局变量定义在函数外,可以被所有的函数共同使用. #include <iostream> ; void display() { printf(&qu ...
- C语言中:static与extern对变量和函数的作用
1.两者对全局变量 static对全局变量,表示定义一个内部变量 extern对全局变量,表示声明一个外部变量 说明: 1.内部变量:定义的变量只能在本文件中访问,不能被其他文件访问. 2.不同文件中 ...
- [整理]C语言中的static静态对象
1.说明外部对象(静态外部变量和静态函数) (1)static 用于说明外部变量或函数,使该对象的作用域限定为被编译原文件的剩余部分,即从对象说明开始到所在源文件的结束部分: (2)被st ...
- C语言中,static关键字作用
static修饰变量 1 在块中使用static修饰变量 它具有静态存储持续时间.块范围和无链接. 即作用域只能在块中,无法被块外的程序调用:变量在程序加载时创建,在程序终止时结束. 它只在编译时初始 ...
随机推荐
- 《转》Frameset布局
前二天在写一个HTML界面,用到了Frameset,主要学习都是在下面的文章里,内容写得很详细,值得推荐大家看下. 网址:http://captaincook.iteye.com/blog/36563 ...
- 有关于web server架构的一个小疑问
今天闲的时候trace route了yahoo和sina的域名,yahoo的如下: 1 1 ms 1 ms <1 ms 172.21.127.1 2 3 ms ...
- 《Android系统开发》笔记
<Android系统开发>笔记1:Android系统概述 Android四层架构: 1. Linux Kernel&driver层 a.依赖于Linux 2.6内核,包含安全性.内 ...
- IE 加速插件之 Google Chrome Frame
前言 IE 8 及以下版本的速度较慢. 特别是前端的js 和 css 内容较多时尤为突出. 就笔者的开发经验来说GWT, Ext JS, raphael , draw2d 等开发的系统在IE下使用是相 ...
- iOS安全攻击和防御(24):敏感的保护方案逻辑(1)
iOS安全攻击和防御(24):敏感的保护方案逻辑(1) Objective-C代码easy被hook.暴露信息太赤裸裸,为了安全,改用C来写吧! 当然不是所有代码都要C来写,我指的是敏感业务逻辑代码. ...
- Java NIO的性能
最近调研了一下mina和netty框架的性能,主要是想了解java nio在单机能支持多少长连接. 首先,mina的qq群有同学反映说单机支持3w长连接是没问题的 其次,http://amix.dk/ ...
- Discount Diesel Time 9150-1 Quartz Wrist watch [WAT022]- US$4.49
Discount Diesel Time 9150-1 Quartz Wrist watch [WAT022]- US$4.49 Diesel Time 9150-1 Quartz Wrist wat ...
- build setting
A build setting is a variable that contains information about how a particular aspect of a product’s ...
- 读 Working with forms 一些心得
Working with forms About this document This document provides an introduction to Django’s form handl ...
- UILabel iOS添加文本控件
UILabel这是iOS控制,这是UIView子类,只有在UIView文字显示功能的基础上加入.UILabel还查看课程和UIView类别似 //1.创建一个视图对象 //2.配置视图 ...