c语言中static 用法

待兔 等级 896 0 0

static在c里面可以用来修饰变量,也可以用来修饰函数。 先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不是堆,不要弄混。

int a ;
int main()
{
    int b ; 
    int c* = (int *)malloc(sizeof(int));
}

a是全局变量,b是栈变量,c是堆变量。 static对全局变量的修饰,可以认为是限制了只能是本文件引用此变量。有的程序是由好多.c文件构成。彼此可以互相引用变量,但加入static修饰之后,只能被本文件中函数引用此变量。 static对栈变量的修饰,可以认为栈变量的生命周期延长到程序执行结束时。一般来说,栈变量的生命周期由OS管理,在退栈的过程中,栈变量的生命也就结束了。但加入static修饰之后,变量已经不再存储在栈中,而是和全局变量一起存储。同时,离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 static对函数的修饰与对全局变量的修饰相似,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。

文件a.c

static int i; //只在a文件中用 int j; //在工程里用 static void init() //只在a文件中用 { } void callme() //在工程中用 { static int sum; }

上面的全局i变量和init()函数只能用在a.c文件中,全局变量sum的作用域只在callme里。变量j和函数callme()的全局限扩充到整个工程文件。所以可以在下面的b.c中用extern关键字调用。extern告诉编译器这个变量或者函数在其他文件里已经被定义了。

文件b.c

extern int j;           //调用a文件里的
extern void callme();   //调用a文件里的
int main()
{
  ...
}

extern的另外用法是当C和C++混合编程时如果c++调用的是c源文件定义的函数或者变量,那么要加extern来告诉编译器用c方式命名函数:

文件A.cpp调用a.c里面的变量i和函数callme()

extern "C"  //在c++文件里调用c文件中的变量
{
   int j;
   void callme();
}
int main()
{
   callme();
}

二 static法则:

  • A、若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
  • B、若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
  • C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;

全局变量有外部、静态两种存储方式。

  • (1)全局变量一般用外部存储方式存储,用保留字extern加以定义。此时,变量的作用域是构成整个程序的所有程序文件,也就是定义的外部变量可供其它程序文件使用。 使用这样的全局变量一定要非常慎重,一旦产生错误,将波及整个程序。
  • (2)如果希望全局变量仅限于本程序文件使用,而其它程序文件中不能引用,这时必须将其存储方式定义为静态存储方式,用保留字static加以定义。此时称为静态外部变量。 例如,在上例文件filel.c中,如果作这样的定义:
static int a:

则变量a的作用域被缩小至本程序文件filel.c,文件file2.c中不能引用。 值得注意的是对全局变量加static,定义为静态存储方式,并不意味着是静态存储;而不加static,是动态存储。两种形式的全局变量(外部变量)都是静态存储方式,都是编译时分配存储空间,但作用域不同。使用静态外部变量,有利于隔离错误,有利于模块化程序设计。 (3)全局变量的缺省存储方式是外部存储方式。 前面章节中的程序没有见到变量的存储类别定义,实际上采用变量的缺省存储方式。对局部变量采用auto方式,对全局变量采用extern方式。这也是至今为止,我们在程序中没有见到auto、extern等的原因。 至此,我们对变量的存储类别及数据类型进行了全面讨论,在此作个小结。

1.变量定义的一般形式

存储类别数据类型变量表;

2.变量定义的作用

①规定了变量的取值范围。 ②规定了变量进行的运行操作。 ③规定了变量的作用域。 ④规定了变量的存储方式。 ⑤规定了变量占用的存储空间。

3.局部变量和全局变量

从作用域角度将变量分为局部变量和全局变量。它们采取的存储类别如下: 局部变量: ①自动变量,即动态局部变量(离开函数,值就消失)。 ②静态局部变量(离开函数,值仍保留)。 ③寄存器变量(离开函数,值就消失)。 ④形式参数可以定义为自动变量或寄存器变量。 全局变量: ①静态外部变量(只限本程序文件使用)。 ②外部变量(即非静态的外部变量,允许其它程序文件引用)。

4.动态存储和静态存储

从变量存在时间可将变量存储分为动态存储和静态存储。静态存储是在整个程序运行时都存在,而动态存储则是在调用函数时临时分配存储单元。 动态存储: ①自动变量(函数内有效)。 ②寄存器变量(函数内有效)。 ③形式参数。 静态存储: ①静态局部变量(函数内有效)。 ②静态外部变量(本程序文件内有效)。 ③外部变量(整个程序可引用)。

5.静态存储区和动态存储区

从变量值存放的位置可将变量存储区分为静态存储区和动态存储区: 内存中静态存储区: ①静态局部变量。 ②静态外部变量。 ③外部变量(可被同一程序其它文件引用)。 内存中动态存储区:自动变量和形式参数。 CPU中的寄存器:寄存器变量。

收藏
评论区

相关推荐

c语言中static 用法
static在c里面可以用来修饰变量,也可以用来修饰函数。 先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不是堆,不要弄混。 c int a ; int main() { int b ; int c (int )malloc(sizeof(int)); } a是全局变量,b是栈变
C语言基础习题50例(九)41-45
习题41 学习static定义静态变量的用法。实现思路:用static声明和未用static声明变量进行对比,即可得出static的作用。代码如下:cinclude <stdio.h int main(){ void func(); int i; for(i 0;i < 10; i){ func(); } return
C++11新特性学习
1、什么是C+11 ========= C++11标准为C++编程语言的第三个官方标准,正式名叫ISO/IEC 14882:2011 - Information technology -- Programming languages -- C++。在正式标准发布前,原名C++0x。它将取代C++标准第二版ISO/IEC 14882:2003 - Progr
C++学习建议
// 转载 C++学习建议 C++缺点之一,是相对许多语言复杂,而且难学难精。许多人说学习C语言只需一本K&R《C程序设计语言》即可,但C++书籍却是多不胜数。我是从C进入C++,皆是靠阅读自学。在此分享一点学习心得。个人认为,学习C++可分为4个层次: 第一层次:C++基础:挑选一本入门书籍,如《C++ Primer》、《C++大学教程》、或Stro
C# 设置鼠标光标位置
C# 设置鼠标光标位置 using System.Drawing; using System.Runtime.InteropServices; namespace ZB.QueueSys.Common { public class MouseHelper {
C#的单例模式 以及 消息分发机制实现
C#单例模式,多线程安全 //Singleton.cs public class Singleton<T> where T : new() {     private static T _instance;     private static object _lock = new object();
Java中的native关键字
**一.  什么是Native Method**    简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去
Java判断中文字符串是否乱码
转自CSDN一个博主的文章,感觉很有用,转发收藏一下。 import java.util.regex.Matcher; import java.util.regex.Pattern; public class ChineseUtill { private static boolean isChinese
java多线程顺序执行并顺序输出ABC问题
1.有A、B、C、D四个线程,A线程输出A, B线程输出B, C线程输出C,D线程输出D,要求, 同时启动四个线程, 按顺序输出ABCD; 本题主要通过join方法来实现顺序输出ABCD。 代码如下: package thread; /** * @author Beauxie */ publ
CLR存储过程
### C# 代码 namespace SayHello { using Microsoft.SqlServer.Server; public class SayHelloClass { [Microsoft.SqlServer.Serve
Android中调用Arm汇编代码
Android NDK中汇编文件和C文件是等价的,直接使用ndk-build就可混合编译.c和.s文件,例如如下一个汇编文件add.s,实现两个整数相加,并返回结果,源码如下:(注意为gnu语法) .text .align 4 .global my\_add .type my\_add, %function my\_add: add r0, r0
C#中的static关键字
要理解static,就必须要先理解另一个与之相对的关键字,那就是auto,其实我们通常声明的不用static修饰的变量,都是auto的,因为它是默认的,就象short和long总是默认为int一样;我们通常声明一个变量: int a; string s; 其实就是: auto int a; auto string s;
C++ 匿名namespace的作用以及它与static的区别
**一、匿名namespace的作用** 在C语言中,如果我们在多个tu(translation unit)中使用了同一个名字做为函数名或者全局变量名,则在链接阶段就会发生重定义错误,为了解决这个问题,我们可以在定义这些标识符(identifier)的时候加上static关键字修饰以限制它只在一个tu范围内可见。 C++继承了C语言中static关键
C++之静态(static)
一、静态数据成员与静态成员函数 ![](https://oscimg.oschina.net/oscnet/ffa0b22a73abad59b139148809cb396f2f7.png) ![](https://oscimg.oschina.net/oscnet/4a3ea07f1817f52046114ff96c8a71743da.png) 二、从
C++四种cast操作符
  C 风格(C-style)强制转型如下:   (T) expression  或   T(expression) //函数风格(Function-style)   两种形式之间没有本质上的不同。   对于具有转换的简单类型而言C 风格转型工作得很好。然而,这样的转换符也能不分皂白地应用于类(class)和类的指针。ANSI-C++标准定义