当前位置:首页 » 《关注互联网》 » 正文

【⛳重走长征路のC语言中static关键字⛳】_谁吃薄荷糖

4 人参与  2022年01月26日 12:00  分类 : 《关注互联网》  评论

点击全文阅读


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


点击全文阅读


本文链接:http://zhangshiyu.com/post/33936.html

函数  对象  声明  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1