C語言中static的語義
1.static變量:
1).靜態局部變量
a.靜態局部變量在函數內定義,生存期為整個源程序,但作用域與局部變量相同,只能在定義該變量的函數內使用。退出該函數后, 盡管該變量還繼續存在,但不能使用它。
b.對基本類型的靜態局部變量若在說明時未賦以初值,則系統自動賦予0值。而對自動變量不賦初值,則其值是不定的。
2).靜態全局變量
全局變量本身就是靜態存儲方式, 靜態全局變量當然也是靜態存儲方式。但是他們的作用域,非靜態全局 變量的作用域是整個源程序(多個源文件可以共同使用); 而靜態全局變量只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。
2.static函數(也叫內部函數):
只能被本文件中的函數調用,而不能被同一程序其它文件中的函數調用。
3. 在C語言中,由於沒有類的概念,所以沒有靜態成員一說,在c中static的作用主要有2個:
一是隱藏功能,對於static修飾的函數和全局變量而言,其作用於局限於所在的文本,不能被其他文本內的函數使用
二是保持持久性功能,對於static修飾的局部變量而言,其存儲區變更到靜態存儲區,程序結束不銷毀
並且,因為存放在靜態區,全局和局部的static修飾的變量,都默認初始化為0。
4.C中靜態數據和靜態函數的用法
C語言中定義一個靜態變量和靜態函數主要是為了滿足某個文件的需求
比如我們在文件List.c中定義
static int count = 0; //靜態變量
static int get_last_node(List *Head);//定義靜態函數
二者的作用域都僅僅在文件List.c中。如果main函數在static int get_last_node(List *Head)
之前定義,那么就應該在頭文件后面用語句:
static int get_last_node(List *Head);//定義靜態函數進行聲明。
如果main定義在static int get_last_node(List *Head)之后則不需要。(建議靜態函數都在頭文件后聲明)
#include<stadio.h>
static int count = 0; //靜態變量
static int get_last_node(List *Head);//定義靜態函數
void main()
{
List *Head;
.....
int ret = get_last_node(Head);
......
}
static int get_last_node(List *Head)
{
.....
return ret;
}
-----------------------------------------------------------
#include<stadio.h>
static int count = 0; //靜態變量
static int get_last_node(List *Head)
{
.....
return ret;
}
void main()
{
List *Head;
.....
int ret = get_last_node(Head);
......
}
------------------------------------------------------------
C++語言中static的語義
在c++中,由於面向對象的思維,它與C語言中的作用有一些不同,有了類中靜態成員的說法。靜態成員不屬於對象,而屬於類。不創建對象也可調用。從代碼形式上來說沒有任何區別。普通類成員函數與靜態成員函數的區別在於普通成員函數有一個隱藏的調用參數(this)指針。所以就是說靜態成員函數沒有對象也可調用。
一、靜態成員變量
類的靜態成員變量是直接與類聯系,屬於類的成員而不是對象,供所有對象共享,存放於全局區,因而不計入類的內存計算。靜態成員變量可以通過類直接訪問。
(1)靜態成員變量的初始化
靜態成員不屬於類的任何對象,所以並不是對象建立時被定義的,所以它不能由類的構造函數初始化(否則每定義一個對象就要初始化一次),一般也不能在類內初始化。
關鍵字static只出現類的內部。
1、在類外定義且初始化
2、常量靜態成員可以在類內初始化
一般來說無論怎樣靜態成員變量都需要在類外進行定義(定義可以初始化賦值,如果不顯示初始化就是默認初始化)
(2))靜態成員變量的訪問
1、使用類作用域運算符直接訪問
2、使用類的對象訪問
3、成員函數可以直接訪問
范例:
#include <iostream> using namespace std; class A { public: A(){} int val(); static int stval(); static int ac; const static int bc=2;//常量靜態成員可以在類內初始化 private: static int dc; int nn; }; int A::ac=1; //類外定義且初始化,//類的靜態成員變量需要在類外分配內存空間 int A::dc=1; int A::stval() { // nn=10; 靜態成員函數不能調用非靜態成員 dc=20; return dc; } int A::val() { dc=ac; //成員函數直接訪問 return dc; } int main() { A a; cout<<a.ac; //使用類的對象訪問 cout<<a.val(); cout<<A::bc; //類作用域運算符直接訪問 cout<<A::stval(); cout<<a.stval(); return 0; }
(3)靜態成員能使用的某些場景,普通成員不可以的
1、靜態成員可以是不完全類型
2、靜態成員可以作為默認實參
3、作為類對象的共享成員
二、靜態成員函數
1、靜態成員函數類似於靜態成員變量都屬於類而不是對象。
2、靜態成員函數僅可以調用類的靜態成員變量,不可以調用普通成員變量。
3、不具有this指針,因而自然不能聲明為const。
4、如果類的成員函數想作為回調函數來使用,一般情況下只能將它定義為靜態成員才行。
class A { public: A(){} int val(); // static int stval ()const; 出錯,不具有this指針 private: static int bc=2;//常量靜態成員可以在類內初始化 };
靜態成員函數在C++中的作用很強大,包括后邊的介紹的單例模式、二階構造模式,都用到靜態成員函數及靜態成員變量。
下邊的圖為靜態成員函數與普通成員函數的比較
關於靜態局部變量參看:https://www.cnblogs.com/liushui-sky/p/5757365.html
在局部變量前加上“static”關鍵字,就成了靜態局部變量。靜態局部變量存放在內存的全局數據區。函數結束時,靜態局部變量不會消失,每次該函數調用時,也不會為其重新分配空間。它始終駐留在全局數據區,直到程序運行結束。靜態局部變量的初始化與全局變量類似.如果不為其顯式初始化,則C++自動為其初始化為0。
靜態局部變量與全局變量共享全局數據區,但靜態局部變量只在定義它的函數中可見。靜態局部變量與局部變量在存儲位置上不同,使得其存在的時限也不同,導致對這兩者操作 的運行結果也不同。
對靜態局部變量的說明:
(1) 靜態局部變量在靜態存儲區內分配存儲單元。在程序整個運行期間都不釋放。而自動變量(即動態局部變量)屬於動態存儲類別,存儲在動態存儲區空間(而不是靜態存儲區空間),函數調用結束后即釋放。
(2) 為靜態局部變量賦初值是在編譯時進行的,即只賦初值一次,在程序運行時它已有初值。以后每次調用函數時不再重新賦初值而只是保留上次函數調用結束時的值。而為自動變量賦初值,不是在編譯時進行的,而是在函數調用時進行,每調用一次函數重新給一次初值,相當於執行一次賦值語句。
(3) 如果在定義局部變量時不賦初值的話,對靜態局部變量來說,編譯時自動賦初值0(對數值型變量)或空字符(對字符型變量)。而對自動變量來說,如果不賦初值,則它的值是一個不確定的值。這是由於每次函數調用結束后存儲單元已釋放,下次調用時又重新另分配存儲單元,而所分配的單元中的值是不確定的。
(4) 雖然靜態局部變量在函數調用結束后仍然存在,但其他函數是不能引用它的,也就是說,在其他函數中它是“不可見”的。
參考:
https://www.cnblogs.com/yulei0713/p/11327169.html
https://www.cnblogs.com/kiplove/p/6875371.html
https://blog.csdn.net/lms1008611/article/details/81408236