static关键字的作用详解

(1)先来介绍它的第一条也是最重要的一条:隐藏。

当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。

下面是a.c的内容


代码如下:

char a = 'A'; // global variable
void msg()
{
    printf("Hello\n");
}

下面是main.c的内容


代码如下:

int main(void)
{   
    extern char a;    // extern variable must be declared before use
    printf("%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。

以上内容出自博客园Mr. Write之手,写的相当清晰易懂,存档方便复习。

下面是中兴通讯2012校招笔试题的一道问答题:

1. static全局变量与普通的全局变量有什么区别 ?

  全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。

  全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。

  这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。

  static全局变量只初使化一次,防止在其他文件单元中被引用;  

2.  static局部变量和普通局部变量有什么区别 ?

  把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。

  static局部变量只被初始化一次,下一次依据上一次结果值;  

3.  static函数与普通函数有什么区别?

   static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static修饰的函数),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件.

(0)

相关推荐

  • C语言中static的作用及C语言中使用静态函数有何好处

    想了解Java中static关键字的作用和用法详细介绍,请点击此处了解详情. 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条,分别是: 一是隐藏功能,对于static修饰的函数和全局变量而言 二是保持持久性功能,对于static修饰的局部变量而言. 三是因为存放在静态区,全局和局部的static修饰的变量,都默认初始化为0 下面我逐一给大家介绍: (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有

  • 浅谈static a[n*m]={0};中static的作用

    正如我们知道的,函数内部的一般变量和数组都在栈区开辟内存,但是栈区的内存是有限的,当我们要开辟的内存较大时,编译器会报错,那我们该如何处理呢? 我们又知道,static int a;表示在全局区为变量a分配内存,同理我们在数组前面加上static之后,系统也为该数组在全局区分配内存,全局区的总内存比较大,一般会满足我们的需求. 如题:当n*m比较大时,这就是为什么static a[n*m]={0};必须带着static的原因了. 以上这篇浅谈static a[n*m]={0};中static的作

  • C#中static静态变量的用法实例

    本文实例讲述了C#中static静态变量的用法.分享给大家供大家参考.具体如下: 使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员static修饰符可用于类.字段.方法.属性.运算符.事件和构造函数,但不能用于索引器.析构函数或类以外的类型   静态全局变量 定义:在全局变量前,加上关键字 static 该变量就被定义成为了一个静态全局变量. 特点: ① .该变量在全局数据区分配内存. ② .初始化:如果不显式初始化,那么将被隐式初始化为0.   静态局部变量 定义:在局部

  • c语言中static的用法详细示例分析

    static在c里面可以用来修饰变量,也可以用来修饰函数.先看用来修饰变量的时候.变量在c里面可分为存在全局数据区.栈和堆里.其实我们平时所说的堆栈是栈而不是堆,不要弄混. 复制代码 代码如下: int a ;int main(){    int b ;     int c* = (int *)malloc(sizeof(int));} a是全局变量,b是栈变量,c是堆变量.static对全局变量的修饰,可以认为是限制了只能是本文件引用此变量.有的程序是由好多.c文件构成.彼此可以互相引用变量,

  • 关于C/C++中static关键字的作用总结

    1.先来介绍它的第一条也是最重要的一条:隐藏.(static函数,static变量均可)当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.举例来说明.同时编译两个源文件,一个是a.c,另一个是main.c. 复制代码 代码如下: //a.cchar a = 'A';               // global variablevoid msg(){     printf("Hello\n");} 复制代码 代码如下: //main.c int main

  • C#类中static变量用法分析

    本文实例讲述了C#类中static变量用法.分享给大家供大家参考.具体分析如下: 先来看一段代码: 复制代码 代码如下: using System; namespace Param { class Class1 { static int i = getNum(); int j = getNum(); static int num = 1; static int getNum() { return num; } [STAThread] static void Main(string[] args)

  • static关键字的作用详解

    (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话,我举例来说明.我们要同时编译两个源文件,一个是a.c,另一个是main.c. 下面是a.c的内容 复制代码 代码如下: char a = 'A'; // global variablevoid msg() {    printf("Hello\n"); } 下面是main.c的内容 复制代码 代码如下: int main(void){   

  • JAVA关键字及作用详解

    Java关键字及其作用 一. 总览: 访问控制 private protected public 类,方法和变量修饰符 abstract class extends final implements interface native new static strictfp synchronized transient volatile 程序控制 break continue return do while if else for instanceof switch case default 异常

  • 浅谈Java中static关键字的作用

    static关键字主要有两种作用: 第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关. 第二,实现某个方法或属性与类而不是对象关联在一起 具体而言,在Java语言中,static主要有4中使用情况:成员变量.成员方法.代码块和内部类 (1)static成员变量: Java类提供了两种类型的变量:用static关键字修饰的静态变量和不用static关键字修饰的实例变量.静态变量属于类,在内存中只有一个复制,只要静态变量所在的类被加载,这个静态变量就会被分配空间,因此就可以被使

  • 详解c++中的 static 关键字及作用

    注:若没有特指是 静态成员时,默认都是普通成员: 1 类中的普通成员 类中的成员变量 和 成员函数 是分开存储的.其中, 1)每个对象都有独立的成员变量:成员变量可以存储在 栈空间.堆空间.全局数据区: 2)所有对象共享类的成员函数:成员函数 只能存储在 代码段: 2 类中的静态成员(static) 类中的静态成员 1.用 static关键字 修饰: 2.可以用 类名::成员名 访问 静态成员: 3.静态成员 属于 整个类: 4.静态成员 是所属类的成员,其它类不能访问: 5.静态成员的内存分配

  • C++中static修饰符的详解及其作用介绍

    目录 概述 静态数据成员 引用静态数据成员 用类名访问数据成员 静态成员函数 综合案例 概述 static (静态) 修饰符是用来控制变量的存储方式和可见性的. 静态局部变量存储在静态区域: static 的性质: 局部特性:作用范围仅限于本函数 静态特性:存储在静态区, 函数调用结束后不孝顺而保留原值. 在下一次调用时, 保留上一次调用结束时的值. 静态数据成员 在我们定义全局变量的时候, 我们会发现一个问题: 我们可以在程序各处自由的修改全局变量的值 (不安全). 静态数据成员的特点: 静态

  • python命名关键字参数的作用详解

    1.说明 *,nkw表示命名关键字参数,是用户想输入的关键字参数名称,定义方式是在nkw前追加*, 2.作用 限制调用者传达的参数名称. 3.实例 # 命名关键字参数 def print_info4(name, age=18, height=178, *, weight, **kwargs): ''' 打印信息函数4,加入命名关键字参数 :param name: :param age: :param height: :param weight: :param kwargs: :return: '

  • java之assert关键字用法案例详解

    Java2在1.4中新增了一个关键字:assert.在程序开发过程中使用它创建一个断言(assertion).,它的语法形式有如下所示的两种形式: 1.assert condition; 这里condition是一个必须为真(true)的表达式.如果表达式的结果为true,那么断言为真,并且无任何行动 如果表达式为false,则断言失败,则会抛出一个AssertionError对象.这个AssertionError继承于Error对象, 而Error继承于Throwable,Error是和Exc

  • java方法及this关键字原理分析详解

    目录 步骤1 .给顾客增加一个吃饭的方法 步骤 2 . 没有加static的属性和方法,一定需要先new对象 步骤 3 . 用new出来的对象去执行eat方法 步骤 4 . 怎么理解c.eat() 步骤 5 . 消息接受器 步骤 6 . 如果有两个顾客? 步骤 7 . 答案 步骤 8 .其实有个this 步骤 9 . 在eat方法里面直接使用this 步骤 10 . 构造方法 步骤 11 . 总结:this的意义是什么? 步骤 12 . 道理我都懂,那static又是什么? 步骤 13 . 本节

  • Java super关键字的用法详解

    目录 super关键字的三种用法: 1. super.成员变量 2. super.成员方法 3. super():调用父类中的构造方法 3.1.1 隐式调用父类无参数构造方法super() 3.1.2 显式调用父类有参数构造方法super(id) super关键字作用:在子类内部调用父类对象 基础语法: 1.在类的继承中,当子类继承了父类, 在构造子类的时候,一定要先帮助父类进行构造: 2. 调用super()必须写在子类构造方法的第一行,以保证在执行任何动作前,对象已经完成了初始化,否则编译不

  • C语言学习之关键字的示例详解

    目录 1. 前言 2. 什么是关键字 3. extern-声明外部符号 4. auto-自动 5. typedef-类型重定义(类型重命名) 6. register-寄存器 6.1 存储器 6.2 register关键字的作用 7. static-静态 7.1 static修饰局部变量 7.2 static修饰全局变量 7.3 static修饰函数 1. 前言 大家好,我是努力学习游泳的鱼.关键字,这名字一听,就很关键.而有些关键字,你可能不是很了解,更别谈使用.所以,这篇文章将带你见识常见的关

随机推荐