C语言中static关键字

用static声明限定外部变量与函数,可以将其后声明的对象的作用域限定为被编译源文件的剩余部分。要降对象指定为静态存储,可以在正常的声明之前加上关键字static作为前缀。
一个声明中最多只能有一个存储类说明符。如果没有指定存储类说明符,则将按照下列规则进行:
在函数内部声明的对象被认为是auto类型;
在函数内部声明的函数被认为是extern类型;
在函数外部声明的对象与函数将被认为是static类型,且具有外部连接。

如果一个对象或函数的第一个外部声明包含static说明符,则该标识符具有内部连接,否则具有外部连接。

1.修饰变量

说明符staitc将声明的对象说明为静态存储类。这种对象可以用在函数内部或函数外部。在函数内部,该说明符将引起存储空间的分配,具有定义的作用。static类型的对象仅在程序开始执行前初始化一次。
如果一个对象的外部声明带有初值,则该声明就是一个定义。如果一个外部对象声明不带有初值,并且不包含extern说明符,则它是一个临时定义。如果对象的定义出现在翻译单元中,则所有临时定义都将仅仅被认为是多余的声明;如果该翻译单元中不存在该对象的定义,则该临时定义将转变为一个初值为0的定义。

在C语言中,全局变量静态变量都是存储在静态存储区的。针对未初始化的全局变量(或静态变量)都被系统默认初始化为0

c99标准,在6.7.8/10中有谈到变量初值(未初始化的静态存储对象一律清零

If an object that has automatic storage duration is not initialized explicitly, its value isindeterminate. If an object that has static storage duration is not initialized explicitly,then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to theserules.

1.1 全局变量

通过static限定外部对象,可以达到隐藏外部对象的目的。
特点:
a.在全局区分配内存;
b.该变量在本文件内从定义开始到文件结束可见;

1.2 局部变量

static也可用于声明内部变量。static类型的内部变量通自动变量一样,是某个特定函数的局部变量,只能在该函数中使用,但它与自动变量不同的是,不管其所在的函数是否被调用,它一直存在,而不像自动变量那样,随着所在函数的被调用和退出而存在和消失。换句话说,static类型的内部变量是一种只能在某个特定函数中使用但一直占据存储空间的变量。
特点:
a.该变量在全局数据区分配内存;
b.它始终驻留在全局数据区,直到程序运行结束;
c. 其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;

Demo:

#include<stdio.h>static int nGlobal;void func1(void)
{static int nLocal = 0;nLocal++;printf("nLocal:%d\r\n",nLocal);
}void func2(void)
{nGlobal = 0;nGlobal++;printf("nGlobal:%d\r\n", nGlobal);
}void func3(void)
{int nTmp = 0;nTmp++;printf("nTmp:%d\r\n",nTmp);
}int main()
{int i = 0;for(i = 0; i < 10; i++){func1();func2();func3();}return 0;
}

打印:

nLocal:1
nGlobal:1
nTmp:1
nLocal:2
nGlobal:1
nTmp:1
nLocal:3
nGlobal:1
nTmp:1
nLocal:4
nGlobal:1
nTmp:1
nLocal:5
nGlobal:1
nTmp:1
nLocal:6
nGlobal:1
nTmp:1
nLocal:7
nGlobal:1
nTmp:1
nLocal:8
nGlobal:1
nTmp:1
nLocal:9
nGlobal:1
nTmp:1
nLocal:10
nGlobal:1
nTmp:1

2.修饰函数

外部的static声明通常多用于变量,当然,它也可用于声明函数。通常情况下,函数名字是全局可访问的,对整个程序的各个部分而言都可见。但是,如果把函数声明为static类型,则该函数名除了对该函数声明所在的文件可见外,其它文件都无法访问。
“static”使函数的作用域仅局限于本文件(所以又称内部函数)。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
特点:
a.静态函数只能在本源文件中使用;
b.在文件作用域中声明的inline函数默认为static类型;

Demo1:正常函数调用,以test()为例
test.c

#include <stdio.h>
void Test();void Test()
{printf("This is test()\n");
}

main.c

#include <stdio.h>
extern  Test();int main()
{Test();return 0;
}

打印:

Demo2:使用static修饰后的test()函数
test.c

#include <stdio.h>
static void Test();static void Test()
{printf("This is test()\n");
}

main.c

#include <stdio.h>
extern  Test();int main()
{Test();return 0;
}

编译报错:

1>------ 已启动生成: 项目: ConsoleApplication1, 配置: Debug Win32 ------
1>test.c
1>main.obj : error LNK2019: 无法解析的外部符号 _Test,该符号在函数 _main 中被引用
1>C:\Users\mints\Documents\Visual Studio 2017\Projects\ConsoleApplication1\Debug\ConsoleApplication1.exe : fatal error LNK1120: 1 个无法解析的外部命令
1>已完成生成项目“ConsoleApplication1.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

精炼总结

对static的作用做一句话总结。首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备默认值0(针对未初始化的全局变量和局部静态变量而言)和持久性

知识扩展:

存储类

存储类分为两类:自动存储类(automatic)和静态存储类(static)。声明对象时使用的一些关键字和声明的上下文共同决定了对象的存储类。

自动存储类对应一个程序块来说是局部的,在退出程序块时该对象将消失。如果没有使用存储类说明符,或者如果使用了auto限定符,则程序块中的声明生成的都是自动存储类对象。声明为register的对象也是自动存储类对象,并且将被存储在机器的快速寄存器中(如果可能的话)。

静态对象可以是某个程序块的局部对象,也可以是所有程序块的外部对象。无论是哪一种情况,在退出和再进入函数或程序块时其值将保持不变。在一个程序块(包括提供函数代码的程序块)内,静态对象用关键字static声明。在所有程序块外部声明且与函数定义在同一级的对象总是静态的。可以通过static关键字将对象声明为某个特定翻译单元的局部对象,这种类型的对象将具有内部连接。当省略显式的存储类或通过关键字extern进行声明时,对象对整个程序来说全局可访问的,并且具有外部连接。

BBS段

BSS(Block Started by Symbol)通常是用来存放程序中未初始化的或者初始化为0全局变量静态变量的一块内存区域。
特点是:可读写的,在程序执行之前BSS段会自动清0。
所以,未初始化的全局变量或静态变量在程序执行之前已经成0了。

引经据典

《The C Programming Language Second Edtion》
https://www.cnblogs.com/ustc-anmin/p/11239257.html
http://c.biancheng.net/cpp/html/436.html
https://www.cnblogs.com/gatsbywang/p/5171416.html
https://www.zhihu.com/question/49111720/answer/114331032

【✊基础不牢,地动山摇のC语言中static关键字✊】相关推荐

  1. C语言中static关键字和break/continue在for/while循环中的作用

    前言 此篇博客对C语言的基础知识稍加总结,包括C语言中的static关键字作用,三大循环语句中出现的break和continue对循环体的影响,常量,生命周期,作用域,字符串,转义字符等等,其中常见的 ...

  2. C语言中static关键字的作用

    在C语言中static的作用如下 第一.在修饰变量的时候,static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放.  第二.static修饰全局变量的时候, ...

  3. C语言中static关键字详解

    C语言中staic关键字很简单,简单到你的任何一个项目中可以不写一个staic关键字也是没有问题的.写这篇章主要是一下自己的staic的理解和应用,当然在章开头依旧要照本宣科简述一下static关键字 ...

  4. C语言中static关键字的作用详解,全网最透彻

    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有 ...

  5. c语言中static关键字用法详解

    概述 static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护. 但是对于c语言初学者,static由于使用灵活,并不容易掌握.本文就static在c语言中的应用进 ...

  6. c语言typeof 变量,c语言中typeof关键字

    为什么因为一个关键字而专门写一篇随笔呢?因为这个关键字在Linux里面地位非同一般!这个关键字typeof在linux内核里面使用非常广泛! 下面这两个等效声明,用于声明int类弄的变量a typeo ...

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

    转自:http://www.jb51.net/article/74830.htm 在C语言中,static的作用有三条:一是隐藏功能,二是保持持久性功能,三是默认初始化为0. 在C语言中,static ...

  8. C语言中static详细分析

    google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大论不知所云要么在关键之处几个字略过,对于想挖掘底层原理的初学者来说参考性不是很大.所以,我这篇博文博采众家之长,把互 ...

  9. c语言中static变量

    c语言中static变量 2009-06-30 20:33:24|  分类:默认分类 |  标签:|字号大中小 订阅 static静态变量声明符. 在声明它的程序块,子程序块或函数内部有效,值保持,在 ...

最新文章

  1. python描述符魔术方法_Python所有特殊方法、魔术方法、 钩子
  2. 基于malloc与free函数的实现代码及分析
  3. 发送json给服务器
  4. 在一基金慈善年会上面发言
  5. adb——Android的ADB工具使用
  6. Transport(传输) 详解
  7. LNMP搭建论坛(php)
  8. 二维数组找鞍点c语言,怎么求一个二维数组的鞍点
  9. 第十课:栈的表示与实现
  10. 3-汇编语言中与内存访问相关的寄存器/操作(DS+数据段+SS/SP+栈相关操作)
  11. 【数字信号处理】基于matlab GUI手机信号频谱+时域分析【含Matlab源码 1042期】
  12. 全国大学生软件测试大赛Web应用测试(八)Web众包测试具体流程
  13. 计算机基础教程(一)
  14. 机器学习在各个领域的实际应用
  15. 地方论坛门户网站运营之我见-上篇
  16. 管理IT外包的七大秘诀
  17. 解决百度网盘下载限速 速度慢问题
  18. cos47度怎么用计算机算,cos47度等于多少
  19. Qt 事件过滤器(秒懂)
  20. c++ crow入门填坑坑

热门文章

  1. Hbase的读写流程
  2. 第2课第3节_Java面向对象编程_继承性_P【学习笔记】
  3. 2019春第四周作业软件
  4. django下载excel,使用django-excel插件
  5. 为PHP设置服务器(Apache/Nginx)环境变量
  6. python并发之concurrent.futures
  7. discuz数据库相关表
  8. c++学习笔记之构造函数
  9. 卷积神经网络算法的一个实现
  10. 纯Python模块发布setup脚本编写示例