C语言中 static的字面意思很容易把我们导入歧途其实它的作用有三条。 1先来介绍它的第一条也是最重要的一条 隐藏。
当我们同时编译多个文件时所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话我举例来说明。我们要同时编译两个源文件一个是a.c另一个是main.c。下面是a.c的内容char a = 'A' ; // global variablevoid msg()
{printf("Hello\n") ;
}
下面是main.c的内容int main(void)
{extern char a; // extern variable must be declared before useprintf("%c ", a) ;
(void)msg() ;return 0;
}
程序的运行结果是
A Hello
你可能会问为什么在a.c中定义的全局变量a和函数msg能在main.c中使用前面说过所有未加static前缀的全局变量和函数都具有全局可见性其它的源文件也能访问。此例中 a是全局变量 msg是函数并且都没有加static前缀因此对于另外的源文件main.c是可见的。
如果加了static就会对其它源文件隐藏。例如在a和msg的定义前加上static main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量而不必担心命名冲突。 Static可以用作函数和变量的前缀对于函数来讲 static的作用仅限于隐藏而对于变量 static还有下面两个作用。 2 static的第二个作用是保持变量内容的持久。存储在静态数据区的变量会在程序刚开始运行时就完成初始化也是唯一的一次初始化。共有两种变量存储在静态存储区全局变量和static变量只不过和全局变量比起来 static可以控制变量的可见范围说到底static还是用来隐藏的。虽然这种用法不常见但我还是举一个例子。
#include <stdio.h>int fun(void) {static int count = 10; //事实上此赋值语句从来没有执行过return count--;
}int count = 1 ;int main(void)
{printf("global\t\tlocal static\n") ;for( ; count <= 10; ++count)printf("%d\t\t%d\n", count, fun() ) ;
return 0;
}
程序的运行结果是global local static
1 10
2 9
3 8
4 7
5 6
6 5
7 4
8 3
9 2
10 1
3 static的第三个作用是默认初始化为0。其实全局变量也具备这一属性 因为全局变量也存储在静态数据区。在静态数据区 内存中所有的字节默认值都是0x00某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵我们可以一个一个地把所有元素都置0然后把不是0的几个元素赋值。如果定义成静态的就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用但又觉得每次在字符数组末尾加’ \0’太麻烦。如果把字符串定义成静态的就省去了这个麻烦 因为那里本来就是’ \0’ 。不妨做个小实验验证一下。
#include <stdio.h>int a;int main(void)
{int i ;static char str[10] ;printf("integer: %d; string: (begin)%s(end)", a, str) ;return 0;
}
程序的运行结果如下integer: 0; string: (begin) (end)
最后对static的三条作用做一句话总结。首先static的最主要功能是隐藏其次因为static变量存放在静态存储区所以它具备持久性和默认值0。
另外
一、 c程序存储空间布局
C程序一直由下列部分组成
1正文段——CPU执行的机器指令部分一个程序只有一个副本只读防止程序由于意外事故而修改自身指令
2初始化数据段数据段——在程序中所有赋了初值的全局变量存放在这里。
3非初始化数据段bss段——在程序中没有初始化的全局变量 内核将此段初始化为0。
4栈——增长方向 自顶向下增长 自动变量以及每次函数调用时所需要保存的信息返回地址环境信息 。
5堆——动态存储分。
|-----------|
| |
|-----------|
|栈|
|-----------|
| | |
| |/ |
| |
| |
| /| |
| | |
|-----------|
|堆|
|-----------|
|未初始化|
|-----------|
|初始化|
|-----------|
|正文段|
|-----------|
二、 面向过程程序设计中的static
1.全局静态变量
在全局变量之前加上关键字static全局变量就被定义成为一个全局静态变量。
1 内存中的位置静态存储区静态存储区在整个程序运行期间都存在
2初始化未经初始化的全局静态变量会被程序自动初始化为0 自动对象的值是任意的除非他被显示初始化
3作用域全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。
定义全局静态变量的好处
<1>不会被其他文件所访问修改
<2>其他文件中可以使用相同名字的变量不会发生**。
2.局部静态变量
在局部变量之前加上关键字static局部变量就被定义成为一个局部静态变量。
1 内存中的位置静态存储区
2初始化未经初始化的全局静态变量会被程序自动初始化为0 自动对象的值是任意的除非他被显示初始化
3作用域作用域仍为局部作用域 当定义它的函数或者语句块结束的时候作用域随之结束。
注 当static用来修饰局部变量的时候它就改变了局部变量的存储位置从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后并没有被销毁而是仍然驻留在内存当中直到程序结束只不过我们不能再对他进行访问。
当static用来修饰全局变量的时候它就改变了全局变量的作用域在声明他的文件之外是不可见的 但是没有改变它的存放位置还是在静态存储区中。
3.静态函数
在函数的返回类型前加上关键字static 函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的但静态函数只是在声明他的文件当中可见不能被其他文件所用。
定义静态函数的好处
<1>其他文件中可以定义相同名字的函数不会发生**
<2>静态函数不能被其他文件所用。
存储说明符auto register extern static对应两种存储期 自动存储期和静态存储期。auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立它在该程序块活动时存在退出该程序块时撤销。
关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局
部变量具有静态存储持续期static storageduration 或静态范围staticextent 。虽然他的值在函数调用之间保持有效但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。
扩展分析:
术语static有着不寻常的历史.起初在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量。随后 static C中有了第二种含义用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字所以仍使用static关键字来表示这第二种含义。最后
C++重用了这个关键字并赋予它与前面不同的第三种含义表示属于一个类而不是属于此类的任何特定对象的变量和函数(与Java中此关键字的含义相同) 。
C语言程序可以看成由一系列外部对象构成这些外部对象可能是变量或函数。而内部变量是指定义在函数内部的函数参数及变量。外部变量定义在函数之外因此可以在许多函数中使用。 由于C语言不允许在一个函数中定义其它函数 因此函数本身只能是“外部的” 。
由于C语言代码是以文件为单位来组织的在一个源程序所有源文件中一个外部变量或函数只能在某个文件中定义一次而其它文件可以通过extern声明来访问它定义外部变量或函数的源文件中也可以包含对该外部变量的extern声明 。
而static则可以限定变量或函数为静态存储。如果用static限定外部变量与函数则可以将该对象的作用域限定为被编译源文件的剩余部分。通过static限定外部对象可以达到隐藏外部对象的目的。因而 static限定的变量或函数不会和同一程序中其它文件中同名的相冲突。如果用static限定内部变量则该变量从程序一开始就拥有内存不会随其所在函数的调用和退出而分配和消失。
C语言中使用静态函数的好处
1. 静态函数会被自动分配在一个一直使用的存储区直到退出应用程序实例避免了调用函数时压栈出栈速度快很多。
2. 关键字“static” 译成中文就是“静态的” 所以内部函数又称静态函数。但此处“static”的含义不是指存储方式而是指对函数的作用域仅局限于本文件。 使用内部函数的好处是不同的人编写不同的函数时不用担心自己定义的函数是否会与其它文件中的函数同名 因为同名也没有关系。c语言中static的语义
1. static变量:
1) .局部a.静态局部变量在函数内定义,生存期为整个源程序但作用域与自动变量相同只能在定义该变量的函数内使用。退出该函数后 尽管该变量还继续存在但不能使用它。b.对基本类型的静态局部变量若在说明时未赋以初值则系统自动赋予0值。而对自动变量不赋初值则其值是不定的。
2) .全局
全局变量本身就是静态存储方式 静态全局变量当然也是静态存储方式。但是他们的作用域非静态全局变量的作用域是整个源程序多个源文件可以共同使用 而静态全局变量则限制了其作用域 即只在定义该变量的源文件内有效 在同一源程序的其它源文
件中不能使用它。
2. static函数也叫内部函数
只能被本文件中的函数调用而不能被同一程序其它文件中的函数调用。区别于一般的非静态函数外部函数static在c里面可以用来修饰变量也可以用来修饰函数。
先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不包含对不要弄混。int a ;main()
{int b ;int c* = (int *)malloc(sizeof(int) ) ;
}a是全局变量 b是栈变量 c是堆变量。static对全局变量的修饰可以认为是限制了只能是本文件引用此变量。有的程序是由好多.c文件构成。彼此可以互相引用变量但加入static修饰之后只能被本文件中函数引用此变量。static对栈变量的修饰可以认为栈变量的生命周期延长到程序执行结束时。一般来说栈变量的生命周期由OS管理在退栈的过程中栈变量的生命也就结束了。但加入static修饰之后变量已经不在存储在栈中而是和全局变量一起存储。 同时离开定义它的函数后不能使用但如再次调用定义它的函数时它又可继续使用 而且保存了前次被调用后留下的值。static对函数的修饰与对全局变量的修饰相似只能被本文件中的函数调用而不能被同一程序其它文件中的函数调用。static声明的变量在C语言中有两方面的特征
1) 、变量会被放在程序的全局存储区中这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。
2) 、变量用static告知编译器 自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
--test.h
------------------------------------------------static void test() ;
------------------------------------------------test.c
------------------------------------------------
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
static void test()
{printf("test. . . . \n") ;
}
main.c
-------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "test.h"int main(int argc, char *argv[] )
{test() ; //如果去掉这个调用程序将可以编译相当于只申明了一个静态函数没有使用它的话不会去找它的实现
//如果不去掉它 将无法编译通过因为静态函数的生命期是本main.c文件 而在此文件中找不到test()的实现。
//如果在此要调用test() ,必须将test.c中的test()实现移到main.c or test.hsystem("PAUSE") ;return 0;
}
----------------------------------------------------------
我认为你改了之后是可以的. .
假设一个函数内定义个静态变量,并在它定义时就给了初值,如:void fun (void)
{static s_cnt = 1 ;
. . .//其他代码
}
那么是在编译的时候赋值给这个静态变量,以后每次调用都不会再让他等于1,而是继续上一次的值
但如果在定义时没有给初值(默认是0) ,但在下一句赋值,如:void fun (void)
{static s_cnt;s_cnt = 1 ;
. . . //其他代码
}
这样每次进来都是s_cnt都是1. .
标题【萤光云双十二 全场6折 15元/月 续费同价】今天站长给大家推荐一家国内云厂商的双十二活动。萤光云总部位于福建福州,其成立于2002 年。主打高防云服务器产品,主要提供福州、北京、上海 BGP 和香港 CN2 节点。萤光云的高防云服务器自带 50G 防御,适合高防建站、游戏高防等业务。这家厂商本次双十二算是性价比很高了。全线产品6折,上海 BGP 云服务器折扣更大 5.5 折(测试了一下是金...
HostKvm是一家成立于2013年的国外主机服务商,主要提供VPS主机,基于KVM架构,可选数据中心包括日本、新加坡、韩国、美国、俄罗斯、中国香港等多个地区机房,均为国内直连或优化线路,延迟较低,适合建站或者远程办公等。商家本月针对香港国际机房提供特别7折优惠码,其他机房全场8折,优惠后2G内存香港VPS每月5.95美元起,支持使用PayPal或者支付宝付款。下面以香港国际(HKGlobal)为...
GreenCloudVPS最近在新加坡DC2节点上了新机器,Dual Xeon Silver 4216 CPU,DDR4内存,10Gbps网络端口,推出了几款大硬盘VPS套餐,基于KVM架构,500GB磁盘起年付30美元。除了大硬盘套餐外,还加推了几款采用NVMe硬盘的常规套餐,最低年付20美元。不过需要提醒的是,机房非直连中国,尤其是电信用户ping值感人,包括新加坡DC1也是如此。大硬盘VPS...