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关键字

    C语言static关键字 static关键字的作用,主要从在程序的生存周期.作用域和在代码段中的位置起作用. 全局变量 静态全局变量 局部变量 静态局部量 生存周期 程序运行到结束 程序运行到结束 函 ...

  2. 利用R语言打造量化分析平台

    利用R语言打造量化分析平台 具体利用quantmod包实现对股票的量化分析 1.#1.API读取在线行情2.#加载quantmod包3.if(!require(quantmod)){4. instal ...

  3. R语言重要数据集分析研究——需要整理分析阐明理念

    1.R语言重要数据集分析研究需要整理分析阐明理念? 上一节讲了R语言作图,本节来讲讲当你拿到一个数据集的时候如何下手分析,数据分析的第一步,探索性数据分析. 统计量,即统计学里面关注的数据集的几个指标 ...

  4. C语言-- static 全局使用示例

    C语言-- static 全局使用示例  前言:看到很多使用Objective-C开发IOS的大牛,有时候会使用static全局变量,相比之下,我却很少用这个,从而很少对其有着比较有实质意义的理解,甚 ...

  5. Go语言的前景分析

    本文为原创文章,转载注明出处,asdfasdfasdf 欢迎扫码关注公众号flysnow_org或者网站http://www.flysnow.org/,第一时间看后续精彩文章.觉得好的话,顺手分享到朋 ...

  6. Go将统治下一个10年?Go语言发展现状分析

    “本文是国内Go语言大中华区首席布道师——许式伟,在QCon2015上海站上的分享.他预测Go语言10年内一定会超过C和java,并且统治这一个10年. Go语言语法及标准库变化 Go从1.0版本到现 ...

  7. 猴子吃桃问题之《C语言经典案例分析》

    猴子吃桃问题之<C语言经典案例分析>一.[什么是猴子吃桃]       猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个.第二天早上又将第一天剩下的桃子吃掉一半 ...

  8. Go语言源码分析之unsafe

    Go语言源码分析之unsafe 1.什么是unsafe unsafe 库让 golang 可以像C语言一样操作计算机内存,但这并不是golang推荐使用的,能不用尽量不用,就像它的名字所表达的一样,它 ...

  9. C语言static

    1. static 变量 静态变量的类型说明符是static. 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量. 例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 ...

随机推荐

  1. OpenJDK1.8.0 源码解析————HashMap的实现(二)

    上一篇文章介绍了HashMap的一部分的知识,算是为下面HashMap的进一步学习做准备吧. 然后写的时候一直在思考的一个问题是,这方面的知识网上的资料也是一抓一大把,即使是这样我为什么还要花费时间去 ...

  2. Memcahce(MC)系列(一)Memcache介绍、使用、存储、算法、优化

    写在前面:前不久在工作中被问到关于MC一致哈希的问题,由于时隔太久差点儿忘记,特前来恶补一下MC,下面是前几年在工作中学习MC时的一些资料,来历不明,特整理一下,希望对大家的学习也能有帮助. 32 的 ...

  3. 《转》Frameset布局

    前二天在写一个HTML界面,用到了Frameset,主要学习都是在下面的文章里,内容写得很详细,值得推荐大家看下. 网址:http://captaincook.iteye.com/blog/36563 ...

  4. java中Executor、ExecutorService、ThreadPoolExecutor介绍(转)

    1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /**     * Executes th ...

  5. dsp下基于双循环缓冲队列的视频采集和显示记录

    对最近在设计的视频采集和显示缓冲机制做一个记录,以便以后使用. 视频采集和显示缓冲机制,其实是参考了Linux下v4L2的驱动机制,其采用输入多缓冲frame,输出多缓冲的切换机制.简单的就是ping ...

  6. C++ STL copy函数效率分析

    在C++编程中,经常会配到数据的拷贝,如数组之间元素的拷贝,一般的人可能都会用for循环逐个元素进行拷贝,在数据量不大的情况下还可以,如果数据量比较大,那么效率会比较地下.而STL中就提供了一个专门用 ...

  7. hdu 1024(dp)

    传送门:Max Sum Plus Plus 题意:从n个数中选出m段不相交的连续子段,求这个和最大. 分析:经典dp,dp[i][j][0]表示不取第i个数且前i个数分成j段达到的最优值,dp[i][ ...

  8. RANSAC - 随机采样一致性算法

    RANSAC范例的正式描述如下: 首先,要给定: 1一个模型,该模型需要最少n个数据点去实例化它的自由参数: 2一组数据点P,P中包含数据点的数量#(P)大于n. 然后, 从P中随机地选择n个点(组成 ...

  9. struts2对action中的方法进行输入校验(2)

    struts2输入校验流程: 1.类型转换器对请求參数运行类型转换,并把转换后的值赋给aciton中的属性 2.假设在运行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext, ...

  10. Visual Prolog 的 Web 专家系统 (8)

    GENI核心 -- 推理引擎(2)流量控制 1.阐述fail."!"而回溯 与其他语言相比,,Prolog最大的特点.这是回溯机制. 回溯机制,还有的主要手段2个月,首先,通过使用 ...