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;
}

报错例如以下:

[[email protected] 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;
}

则会顺利编译连接。

执行程序后的结果例如以下:

[[email protected] static]$ gcc -Wall file2.c file1.c -o file2

[[email protected] 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,例如以下:

[[email protected] 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;
}

[[email protected] static]$ gcc -Wall file2.c file1.c -o file2

[[email protected] 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;
}

编译时会报错:

[[email protected] 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;
}

编译执行:

[[email protected] static]$ gcc -Wall file2.c file1.c -o file2

[[email protected] static]$ ./file2

returnVal=6

static功能,可以解决同名不同功能的问题,在原始文档是非常好,因为在其他的源文件源文件的static功能是不可见的。

希望你有很多监督当地翼的~~

时间: 2024-10-14 04:44:00

C语言static 具体分析的相关文章

[转]易语言消息机制分析(消息拦截原理)

标 题: [原创]易语言消息机制分析(消息拦截原理)作 者: 红绡枫叶时 间: 2014-12-17,12:41:44链 接: http://bbs.pediy.com/showthread.php?t=195626 我自己做了个易语言的sig签名,方便分析的时候用.易语言例子是静态编译的.版本 5.11易语言其实是基于mfc的,它依然需要mfc的消息派发机制,只不过,自己当了系统与用户间的代理人.所有的消息都要经它转发而已.我在MFC的消息派发函数_AfxDispatchCmdMsg下断点,总

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

"本文是国内Go语言大中华区首席布道师--许式伟,在QCon2015上海站上的分享.他预测Go语言10年内一定会超过C和java,并且统治这一个10年. Go语言语法及标准库变化 Go从1.0版本到现在(2015年)已经有三年多的时间,大的版本发布了五个,下面大家一起看看每个大版本分别都改了什么,当然这里不可能把所有的细节都提到,但我认为重要的会提出来. 首先是Go1.1,Go1.0于2012年4月发布,此后基本维持了每半年发布一个新版本的时间间隔.Go1.5比较例外,在Go1.5的拖累下,Go

Java语言特点及分析

Java语言特点及分析 Java是一门面向对象编程语言. (Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程.) Java具有简单性.面向对象.分布性.健壮性.安全性.平台独立与可移植性.多线程.动态性等特点 .Java可以编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序等. Java语言的这些特点体现了java的如下特性: 能够快速入门 编写的程序代码较少 编写较好的程序代码 更快速的开发程序 利用百分之百纯Java

go语言,简单分析和了解

Go 本地化 该指南也有其他语言版本: Brazilian Portuguese — Português do Brasil Catalan — Català Spanish — Español French - Français Hebrew — ???????? Japanese — 日本語 Korean — ??? Romanian - Român? Chinese — 普通话 Go Playground 这个指南构建在 Go Playground 之上,这是一个运行在 golang.or

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

C语言-- static 全局使用示例  前言:看到很多使用Objective-C开发IOS的大牛,有时候会使用static全局变量,相比之下,我却很少用这个,从而很少对其有着比较有实质意义的理解,甚至更别说运用它了. 今天,经过一番思考和自己尝试使用和测试一下static全局变量,发现在有的时候是很有作用的,特此写下笔记. 一开始,我对上面的打印结果有一些疑惑,但是一想到import语句的作用其实就相当于需要导入的文件中的代码拷贝进当前代码import的位置. 然后进一步想到: 备份在百度云的

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

1.R语言重要数据集分析研究需要整理分析阐明理念? 上一节讲了R语言作图,本节来讲讲当你拿到一个数据集的时候如何下手分析,数据分析的第一步,探索性数据分析. 统计量,即统计学里面关注的数据集的几个指标,常用的如下:最小值,最大值,四分位数,均值,中位数,众数,方差,标准差,极差,偏度,峰度 先来解释一下各个量得含义,浅显就不说了,这里主要说一下不常见的 众数:出现次数最多的 方差:每个样本值与均值的差得平方和的平均数 标准差:又称均方差,是方差的二次方根,用来衡量一个数据集的集中性 极差:最大值

03-第一个C语言程序的分析

一.代码分析 二.开发和运行C程序的步骤 三.总结 说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能够快速上手C语言.如果你还没有编程经验,或者对C语言.iOS开发不感兴趣,请忽略 在上一篇中我们已经创建了一个C程序,接下来分析一下里面的代码. 项目结构如下: 回到顶部 一.代码分析 打开项目中的main.c文件(C程序的源文件拓展名为.c),可以发现它是第一个C程序中的唯一一个源文件,代码如下: 1 #include <stdio.h> 2 3 int

C++应用程序性能优化(三)——C++语言特性性能分析

C++应用程序性能优化(三)--C++语言特性性能分析 一.C++语言特性性能分析简介 通常大多数开发人员认为,汇编语言和C语言比较适合编写对性能要求非常高的程序,C++语言主要适用于编写复杂度非常高但性能要求并不是很高的程序.因为大多数开发人员认为,C++语言设计时因为考虑到支持多种编程模式(如面向对象编程和范型编程)以及异常处理等,从而引入了太多新的语言特性.新的语言特性往往使得C++编译器在编译程序时插入了很多额外的代码,会导致最终生成的二进制代码体积膨胀,而且执行速度下降.但事实并非如此

C语言中的static 详细分析

转自: http://blog.csdn.net/keyeagle/article/details/6708077 google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大论不知所云要么在关键之处几个字略过,对于想挖掘底层原理的初学者来说参考性不是很大.所以,我这篇博文博采众家之长,把互联网上的资料整合归类,并亲手编写程序验证之. C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重