【✊基础不牢,地动山摇のC语言中static关键字✊】
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:12.修飾函數
外部的static聲明通常多用于變量,當然,它也可用于聲明函數。通常情況下,函數名字是全局可訪問的,對整個程序的各個部分而言都可見。但是,如果把函數聲明為static類型,則該函數名除了對該函數聲明所在的文件可見外,其它文件都無法訪問。
“static”使函數的作用域僅局限于本文件(所以又稱內部函數)。使用內部函數的好處是:不同的人編寫不同的函數時,不用擔心自己定義的函數,是否會與其它文件中的函數同名。
特點:
a.靜態函數只能在本源文件中使用;
b.在文件作用域中聲明的inline函數默認為static類型;
Demo1:正常函數調用,以test()為例
test.c
main.c
#include <stdio.h> extern Test();int main() {Test();return 0; }打印:
Demo2:使用static修飾后的test()函數
test.c
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关键字✊】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试官是如何发掘有潜力的产品经理的?
- 下一篇: 2021中国出口跨境电商发展研究报告