C语言再学习 -- 存储类、链接
這一章是我看的時(shí)間最長的一章了,表面上是有很多關(guān)鍵字和幾個(gè)函數(shù)需要學(xué)習(xí),其實(shí)我知道是自己最近不在狀態(tài)了,做項(xiàng)目沒進(jìn)展,看書看不下去,兩頭都放不下,最后兩頭都沒有做好。不由的想起一句話,你不快樂是因?yàn)?#xff1a;你可以像只豬一樣懶,卻無法像只豬一樣,懶得心安理得。好了,言歸正傳,進(jìn)入正題:
一、存儲(chǔ)類
C為變量提供了5種不同的存儲(chǔ)類型,或稱存儲(chǔ)類。
下面是C的5種存儲(chǔ)類:
自動(dòng) —— 在一個(gè)代碼塊內(nèi)(或在一個(gè)函數(shù)頭部作為參量)聲明的變量,無論有沒有存儲(chǔ)類修飾符 auto,都屬于自動(dòng)存儲(chǔ)類。該類具有自動(dòng)存儲(chǔ)時(shí)期、代碼塊作用域和空鏈接。如未經(jīng)初始化,它的值是不定的。
寄存器 —— 在一個(gè)代碼塊內(nèi)(或在一個(gè)函數(shù)頭部作為變量)使用存儲(chǔ)類修飾符 register 聲明的變量屬于寄存器存儲(chǔ)類。該類具有自動(dòng)存儲(chǔ)時(shí)期、代碼塊作用域和空鏈接,并且您無法獲得其地址。把一個(gè)變量聲明為寄存器變量可以指示編譯器提供可用的最快訪問。如未經(jīng)初始化,它的值是不定的。
靜態(tài)、空鏈接 —— 在一個(gè)代碼塊內(nèi)使用存儲(chǔ)類修飾符 static 聲明的變量屬于靜態(tài)空鏈接存儲(chǔ)類。該類具有靜態(tài)存儲(chǔ)時(shí)期、代碼作用域和空鏈接,僅在編譯時(shí)初始化一次。如未明確初始化,它的字節(jié)都被設(shè)定為0。
靜態(tài)、外部鏈接 —— 在所有函數(shù)外部定義、未使用存儲(chǔ)類修飾符 static 的變量屬于靜態(tài)、外部鏈接存儲(chǔ)類。該類具有靜態(tài)存儲(chǔ)時(shí)期、文件作用域和外部鏈接,僅在編譯時(shí)初始化一次。如未明確初始化,它的字節(jié)都被設(shè)定為0。
靜態(tài)、內(nèi)部鏈接 —— 在所有函數(shù)外部定義、使用存儲(chǔ)類修飾符 static 的變量屬于靜態(tài)、內(nèi)部鏈接存儲(chǔ)類。該類具有靜態(tài)存儲(chǔ)時(shí)期、文件作用域和內(nèi)部鏈接,僅在編譯時(shí)初始化一次。如未明確初始化,它的字節(jié)都被設(shè)定為0。
這5種存儲(chǔ)類有一個(gè)共同之處:在決定了使用哪一個(gè)存儲(chǔ)類之后,就自動(dòng)決定了作用域和存儲(chǔ)時(shí)期。
其實(shí)還有一種選擇就是使用 malloc() 函數(shù)來分配和管理內(nèi)存,該函數(shù)返回一個(gè)指向具有所請求字節(jié)數(shù)的內(nèi)存塊的指針。將這一內(nèi)存的地址作為參數(shù)來?xiàng)l用函數(shù)free(),可以使該內(nèi)存塊重新可用。
| 存儲(chǔ)類 | 時(shí)期 | 作用域 | 鏈接 ? ? | 聲明方式 |
| 自動(dòng) ? ? ?? | 自動(dòng) ? ? ? ?? | 代碼塊 | 空 | 代碼塊內(nèi) |
| 寄存器 | 自動(dòng) | 代碼塊 ? ? | 空 | 代碼塊內(nèi),使用關(guān)鍵字register ? ? ?? |
| 具有外部鏈接的靜態(tài) ? ? | 靜態(tài) | 文件 | 外部 | 所有函數(shù)之外 |
| 具有內(nèi)部鏈接的靜態(tài) | 靜態(tài) | 文件 | 內(nèi)部 | 所有函數(shù)之外,使用關(guān)鍵字static |
| 空鏈接的靜態(tài) | 靜態(tài) | 代碼塊 | 空 | 代碼塊內(nèi),使用關(guān)鍵字static |
上面提到的一些術(shù)語如:作用域、鏈接和存儲(chǔ)時(shí)期。我們來做一下了解。
1、作用域
作用域描述了程序中可以訪問一個(gè)標(biāo)識符的一個(gè)或多個(gè)區(qū)域。一個(gè)C變量的作用域可以是代碼塊作用域、函數(shù)原型作用域,或者文件作用域。
代碼塊作用域:
double blocky (double cleo) {double patcrick = 0.0;int i;for (i = 0; i < 10; i++){double q = cleo * i; /*q作用域的開始*/...patrick * = q; } /*q作用域的結(jié)束*/return patrick; }
上面代碼中的變量 cleo 和 patrick 都有直到結(jié)束花括號的代碼塊作用域,q的作用域被限制在內(nèi)部代碼塊內(nèi),只有該代碼塊內(nèi)的代碼可以訪問q。
由上可知,代碼塊中定義的變量,從該變量被定義的地方到包含該定義的代碼塊的末尾該變量可見。另外,函數(shù)的形式參量盡管在函數(shù)的開始花括號前進(jìn)行定義,同樣也具有代碼塊作用域,隸屬于包含函數(shù)體的代碼塊。
函數(shù)原型作用域:
適用于函數(shù)原型中使用的變量名,如下所示:
int mighty (int mouse, double large); int mighty (int , double ); (同上)
函數(shù)原型作用域從變量定義處一直到原型聲明的末尾,這意味著編譯器在處理一個(gè)函數(shù)原型的參數(shù)是,它所關(guān)心的只是該參數(shù)的類型。
文件作用域:
一個(gè)在所有函數(shù)之外定義的變量具有文件作用域,具有文件作用域的變量從它定義處到包含該定義的文件結(jié)尾都是可見的。
#include <stdio.h> int unite = 0; void critic (void); int main (void) {...return 0; }void critic (void) {... }
這里,變量 units 具有文件作用域,在 main () 和 critic () 中都可以使用它。因?yàn)樗鼈兛梢栽诓恢挂粋€(gè)函數(shù)中使用,文件作用域變量也被稱為全局變量。
2、鏈接
一個(gè)C變量具有下列鏈接之一:外部鏈接、內(nèi)部鏈接、空鏈接。
外部鏈接:
一個(gè)具有外部鏈接的變量可以在一個(gè)多文件程序的任何地方使用。
int n = 5; /*文件作用域,外部鏈接,未使用 static */ int main (void) {...return 0; }
內(nèi)部鏈接:
一個(gè)具有內(nèi)部鏈接的變量可以在一個(gè)文件的任何地方使用。
static int dodgers = 3; /*文件作用域,內(nèi)部鏈接,使用了 static ,該文件所私有*/ int main (void) {...return 0; }
具有代碼塊作用域或者函數(shù)原型作用域的變量有空鏈接,意味著它們是由其定義所在的代碼塊或函數(shù)原型所私有的。
double blocky (double cleo) {double patcrick = 0.0; /*代碼塊作用域,空鏈接,該代碼塊所私有*/int i;for (i = 0; i < 10; i++){double q = cleo * i; /*q作用域的開始*/...patrick * = q; } /*q作用域的結(jié)束*/return patrick; }
3、存儲(chǔ)時(shí)期
一個(gè)C變量有以下兩種存儲(chǔ)時(shí)期之一:靜態(tài)存儲(chǔ)時(shí)期和自動(dòng)存儲(chǔ)時(shí)期。
靜態(tài)存儲(chǔ)時(shí)期:
如果一個(gè)變量具有靜態(tài)存儲(chǔ)時(shí)期,它在程序執(zhí)行期間將一直存在。具有文件作用域的變量具有靜態(tài)存儲(chǔ)時(shí)期。
注意對于具有文件作用域的變量,關(guān)鍵字 static 表明鏈接類型,并非存儲(chǔ)時(shí)期。一個(gè)使用 static 聲明了的文件作用域變量具有內(nèi)部鏈接,而所有的文件作用域變量,無論它具有內(nèi)部鏈接,還是具有外部鏈接,都具有靜態(tài)存儲(chǔ)時(shí)期。
總結(jié)上面這句話就是, static 修飾的靜態(tài)全局變量,具有內(nèi)部鏈接,不能被其他文件使用。
自動(dòng)存儲(chǔ)時(shí)期:
具有代碼塊作用域的變量,一般情況下具有自動(dòng)存儲(chǔ)時(shí)期。
在程序進(jìn)入定義這些變量的代碼塊時(shí),將為這些變量分配內(nèi)存;當(dāng)退出這個(gè)代碼塊時(shí),分配的內(nèi)存將被釋放。
4、自動(dòng)變量
屬于自動(dòng)存儲(chǔ)類的變量具有自動(dòng)存儲(chǔ)時(shí)期、代碼塊作用域和空鏈接。默認(rèn)情況下,在代碼塊或函數(shù)的頭部定義的任意變量都屬于自動(dòng)存儲(chǔ)類。
關(guān)鍵字auto:
關(guān)鍵字auto稱為存儲(chǔ)類說明符。
int main (void) {auto int p; } 為了表明有意覆蓋一個(gè)外部函數(shù)定義時(shí),或者為了表明不能把變量改變?yōu)槠渌鎯?chǔ)類這一點(diǎn)很重要時(shí),可以這樣做。
代碼塊作用域和空鏈接意味著只有變量定義所在的代碼塊才可以通過名字訪問變量(當(dāng)然,可以用參數(shù)想其他函數(shù)傳送該變量的值和地址,但那是以間接的方式知道的)。另一個(gè)函數(shù)可以使用具有同樣名字的變量,但那將是存儲(chǔ)在不同內(nèi)存位置中的一個(gè)獨(dú)立變量。
int loop (int n) {int m; // m的作用域scanf ("%d, &m");{int i; //m 和 i 的作用域for (i = m; i < n; i++) put ("i is local to a sub-block\n");}return m; //m的作用域, i 已經(jīng)消失 }
如上嵌套代碼塊中,只有定義變量的代碼塊及其內(nèi)部的任何代碼塊可以訪問的變量,變量 i 僅在內(nèi)層花括號中是可見的。如果試圖在內(nèi)層代碼塊之前或之后使用該變量,將得到一個(gè)編譯錯(cuò)誤。
如果在內(nèi)層代碼塊定義了一個(gè)具有和外層代碼塊變量同一個(gè)名字的變量,我們稱之為內(nèi)層定義覆蓋了外部定義,但當(dāng)運(yùn)行離開內(nèi)層代碼塊時(shí),外部變量重新恢復(fù)作用。
#include <stdio.h> int main (void) {int x = 30;printf ("x in outer block : %d\n", x);{int x = 77; printf ("x int inner block : %d\n", x);}printf ("x in outer block : %d\n", x);while (x++ < 33){int x = 100;x++;printf ("x in while loop : %d\n", x);}printf ("x in outer block : %d\n", x);return 0; } 輸出結(jié)果: x in outer block : 30 x int inner block : 77 x in outer block : 30 x in while loop : 101 x in while loop : 101 x in while loop : 101 x in outer block : 34
1)不帶 {} 的代碼塊
語句若為循環(huán)或者 if 語句的一部分,即使沒有使用 { },也認(rèn)為是一個(gè)代碼塊。更完整地說,整個(gè)循環(huán)是該循環(huán)所在代碼塊的子代碼塊,而循環(huán)體是整個(gè)循環(huán)代碼塊的子代碼塊。
#include <stdio.h> int main (void) {int n = 10;printf ("Initially, n = %d\n", n);for (int n = 1; n < 3; n++)printf ("loop 1: n = %d\n", n);printf ("After loop 1, n = %d\n", n);for (int n = 1; n < 3; n++){printf ("loop 2 index n = %d\n", n);int n = 30;printf ("loop 2 n = %d\n", n);n++;}printf ("After loop 2, n = %d\n", n);return 0; } 輸出結(jié)果: Initially, n = 10 loop 1: n = 1 loop 1: n = 2 After loop 1, n = 10 loop 2 index n = 1 loop 2 n = 30 loop 2 index n = 2 loop 2 n = 30 After loop 2, n = 10
注意,有些編譯器可能不支持這些新的C99作用域規(guī)則,需要使用 -std=c99選項(xiàng)來激活這些規(guī)則:
例如: gcc -std=c99 forc99.c
2)自動(dòng)變量的初始化
除非顯式的初始化自動(dòng)變量,否則它不會(huì)被自動(dòng)初始化。
int main (void) {int n;int m = 5; }變量 m 的初始化為5,而變量 n 的初值則是先前占用分配給它的空間任意值。不要指望這個(gè)值是 0 。除非你對自動(dòng)變量進(jìn)行顯示的初始化,否則當(dāng)自動(dòng)變量創(chuàng)建時(shí),它們的值總是垃圾值。
#include <stdio.h> int main (void) {int a;int b = a + 3;printf ("a = %d, b = %d\n", a, b);return 0; }輸出結(jié)果: a = 134513705, b = 134513708
倘若一個(gè)非常量表達(dá)式中所用到的變量先前定義過的話,可將自動(dòng)變量初始化為該表達(dá)式:
int main (void) {int n = 1;int m = 5 * n; //使用先前定義過的變量 }
5、寄存器變量
寄存器變量多是存放在一個(gè)寄存器而非內(nèi)存中,所以無法獲得寄存器變量的地址。具有代碼塊作用域、空鏈接以及自動(dòng)存儲(chǔ)時(shí)期。通過使用存儲(chǔ)類說明符 register 可以聲明寄存器變量:
int main (void) {register int n; } 可以把一個(gè)形式參量請求為寄存器變量,只需在函數(shù)頭部使用 register 關(guān)鍵字:
void macho (register int n) 可以使用 register 聲明的類型是有限的。例如,處理器可能沒有足夠大的寄存器來容納 double 類型。
6、具有代碼塊作用域的靜態(tài)變量
“靜態(tài)”是指變量的位置固定不動(dòng),而非變量不可變。具有文件作用域的變量自動(dòng)(也是必須的)具有靜態(tài)存儲(chǔ)時(shí)期。也可以創(chuàng)建具有代碼塊作用域,兼具靜態(tài)存儲(chǔ)的局部變量。這些變量和自動(dòng)變量具有相同的作用域,但當(dāng)包含這些變量的函數(shù)完成工作時(shí),它們并不消失。也就是說,這些變量具有代碼塊作用域、空鏈接,卻有靜態(tài)存儲(chǔ)時(shí)期。從一次函數(shù)調(diào)用到下一次調(diào)用,計(jì)算機(jī)都記錄著它們的值。這樣的變量通過使用存儲(chǔ)類說明符 static (這提供了靜態(tài)存儲(chǔ)時(shí)期)在代碼塊內(nèi)聲明(這提供了代碼塊作用域和空鏈接)創(chuàng)建。
#include <stdio.h> void trystat (void); int main (void) {int count;for (count = 1; count <= 3; count++){printf ("Hello World %d\n", count);trystat ();}return 0; }void trystat (void) {int fade = 1;static int stay = 1;printf ("fade = %d and stay = %d\n", fade++, stay++); } 輸出結(jié)果: Hello World 1 fade = 1 and stay = 1 Hello World 2 fade = 1 and stay = 2 Hello World 3 fade = 1 and stay = 3
7、具有外部鏈接的靜態(tài)變量
具有外部鏈接的靜態(tài)變量具有文件作用域,外部鏈接和靜態(tài)存儲(chǔ)時(shí)期。這一類型有時(shí)被稱為外部存儲(chǔ)類,這一類型的變量被稱為外部變量。把變量的定義聲明放在所有函數(shù)之外,即創(chuàng)建了一個(gè)外部變量。為了使程序更加清晰,可以在使用外部變量的函數(shù)中通過使用 extern 關(guān)鍵字來再次聲明它。如果變量是在別的文件中定義,使用 extern 來聲明該變量就是必須的。
int n; /*外部定義的變量*/ double Up[100]; /*外部定義的數(shù)組*/ extern char Coal; /*必須的聲明,因?yàn)镃oal在其他文件中定義*/void next (void); int main (void) {extern double Up[]; /*可選的聲明,此處不必指明數(shù)組大小*/extern int n; /*可選的聲明,如果將extern漏掉,就會(huì)建立一個(gè)獨(dú)立的自動(dòng)變量*/ }void next (void) {... }
下列 3 個(gè)例子展示了外部變量和自動(dòng)變量的 4 種可能組合:
/*例1*/ int H; int magic (); int main (void) {extern int H; /*聲明H為外部變量*/... }int magic () {extern int H; /*與上面的H是同一變量*/ }/*例2*/ int H; int magic (); int main (void) {extern int H; /*聲明H為外部變量*/... }int magic () {... /*未聲明H,但知道該變量*/ }/*例3*/ int H; /*對main()和magic()不可見,但是對文件中其他不單獨(dú)擁有局部H的函數(shù)可見*/ int magic (); int main (void) {int H; /*聲明H, 默認(rèn)為自動(dòng)變量,main()的局部變量*/... }int P;/*對magic()可見,對main()不可見,因?yàn)镻聲明子啊main()之后*/ int magic () {auto int H; /*把局部變量H顯式地聲明為自動(dòng)變量*/ }
這些例子說明了外部變量的作用域:從聲明的位置開始到文件結(jié)尾為止。它們也說明了外部變量的生存期。
外部變量H和P存在的時(shí)間與程序運(yùn)行時(shí)間一樣,并且它們不局限于任一函數(shù),在一個(gè)特定函數(shù)返回時(shí)并不消失。
1)外部變量初始化
外部變量可以被顯式地初始化,如果不對外部變量初始化,則它們將自動(dòng)被賦初值 0. 這一原則也適用于外部定義的數(shù)組元素。不同于自動(dòng)變量,只可以用常量表達(dá)式來初始化文件作用域變量。
int x = 10; //可以, 10是常量 int y = 3 + 20; //可以,一個(gè)常量表達(dá)式 size_t = sizeof (int); //可以,一個(gè)常量表達(dá)式 int x2 = 2 * x; //不可以, x是一個(gè)變量 (只要類型不是一個(gè)變長數(shù)組,sizeof表達(dá)式就被認(rèn)為是常量表達(dá)式)
#include <stdio.h> int units = 0; //一個(gè)外部變量 void critic (void); int main (void) {extern int units; //可選的二次聲明printf ("How many pounds to a firkin of butter?\n");scanf ("%d", &units);while (units != 56)critic ();printf ("You must have looked it up!\n");return 0; }void critic (void) { //這里省略了可選的二次聲明printf ("No luck, chummy. Try again\n");scanf ("%d", &units); } 輸出結(jié)果: How many pounds to a firkin of butter? 23 No luck, chummy. Try again 56 You must have looked it up!
在上述例子中,聲明主要是使程序的可讀性更好。存儲(chǔ)類說明符 extern 告訴編譯器在該函數(shù)中用到的 units 都是指同一個(gè)在函數(shù)外部(甚至在文件之外)定義的變量。再次,main()和 critic ()都使用了外部定義的 units。
3)定義和聲明
可參看:C語言再學(xué)習(xí) 2--聲明與定義
這里需要注意的是,關(guān)鍵字 extern 用于聲明,而非定義。
8、具有內(nèi)部鏈接的靜態(tài)變量
具有內(nèi)部鏈接的靜態(tài)變量,具有靜態(tài)存儲(chǔ)時(shí)期、文件作用域以及內(nèi)部鏈接。通過使用存儲(chǔ)類說明符 static 在所有函數(shù)外部進(jìn)行定義(正如定義外部變量那樣)來創(chuàng)建一個(gè)這樣的變量。
int n = 1; //外部鏈接 static int m = 1; //具有內(nèi)部鏈接的靜態(tài)變量 int main (void) {extern int n; //使用全局變量 nextern int m; //使用全局變量 m }
可以在函數(shù)中使用存儲(chǔ)類說明符 extern 來再次聲明任何具有文件作用域的變量。這樣的聲明并不改變鏈接。
9、存儲(chǔ)類說明符
C語言中有 5 個(gè)作為存儲(chǔ)類說明符的關(guān)鍵字,分別是 auto、register、static、extern 以及 typedef。關(guān)鍵字typedef 與內(nèi)存存儲(chǔ)無關(guān),由于語法原因被歸入此類。
在文章:C語言再學(xué)習(xí) 18--關(guān)鍵字? ? 里面我們將詳細(xì)介紹各個(gè)關(guān)鍵字。
現(xiàn)在簡單了解一下這五個(gè)存儲(chǔ)類說明符的關(guān)鍵字:
說明符 auto 表明一個(gè)變量具有自動(dòng)存儲(chǔ)時(shí)期。該說明符只能用于在具有代碼塊作用域的變量聲明中,而這樣的變量已經(jīng)擁有自動(dòng)存儲(chǔ)時(shí)期,因此它主要用來明確指出意圖,使程序更易讀。
說明符 register也只能用于具有代碼塊作用域的變量。它將一個(gè)變量歸入寄存器存儲(chǔ)類,這相當(dāng)于請求將該變量存儲(chǔ)在一個(gè)寄存器內(nèi),以更快地存取。它的使用也使得不能獲得變量的地址。
說明符 static在用于具有代碼塊的作用域的變量的聲明時(shí),使該變量具有靜態(tài)存儲(chǔ)時(shí)期,從而得以在程序運(yùn)行期間(即使在包含該變量的代碼塊沒有運(yùn)行時(shí))存在并保留其值。變量仍具有代碼塊作用域和空鏈接。static 用于具有文件作用域的變量的聲明時(shí),表明該變量具有內(nèi)部鏈接。
說明符 extern表明在聲明一個(gè)已經(jīng)在別處定義了的變量。如果包含 extern 的聲明具有文件作用域,所指向的變量必須具有外部鏈接。如果包含 extern 的聲明具有代碼塊作用域,所指向的變量可能具有外部鏈接也可能具有內(nèi)部鏈接,這取決于該變量的定義聲明。
//parta.c #include <stdio.h> void report_count (); void accumulate (int k); int count = 0; //文件作用域,外部鏈接 int main (void) {int value; //自動(dòng)變量register int i; //寄存器變量printf ("Enter a positive integer (0 to quit): ");while (scanf ("%d", &value) == 1 && value > 0){++count; //使用文件作用域變量for (i = value; i >= 0; i--)accumulate (i);printf ("Enter a posotove integer (0 to quit):");}report_count ();return 0; }void report_count () {printf ("Loop executed %d times\n", count); } //partb.c #include <stdio.h> extern int count; //引用聲明,外部鏈接 static int total = 0; //文件作用域、靜態(tài)定義,內(nèi)部鏈接 void accumulate (int k); //原型 void accumulate (int k) //k 具有代碼塊作用域,空鏈接 {static int subtotal = 0; //靜態(tài)、空鏈接if (k <= 0){printf ("Loop cycle: %d\n", count);printf ("subtotal: %d; total: %d\n", subtotal, total);subtotal = 0;}else{subtotal += k;total += k;} } gcc parta.c partb.c -o part 輸出結(jié)果: Enter a positive integer (0 to quit): 5 Loop cycle: 1 subtotal: 15; total: 15 Enter a posotove integer (0 to quit):10 Loop cycle: 2 subtotal: 55; total: 70 Enter a posotove integer (0 to quit):2 Loop cycle: 3 subtotal: 3; total: 73 Enter a posotove integer (0 to quit):0 Loop executed 3 times
10、存儲(chǔ)類和函數(shù)
外部函數(shù)可被其他文件中的函數(shù)調(diào)用,而靜態(tài)函數(shù)只可以在定義它的文件中使用。例如,考慮一個(gè)包含如下函數(shù)聲明的文件:
double gamma (); //默認(rèn)為外部的 static double beta (); //靜態(tài)函數(shù) extern double delta (); 函數(shù)gamma ()和delta ()可被程序的其他文件中的函數(shù)使用,而beta ()則不可以,因?yàn)閎eta ()被限定在一個(gè)文件內(nèi),故可在其他文件中使用相同名稱的不同函數(shù)。使用 static 存儲(chǔ)類的原因之一就是創(chuàng)建為一個(gè)特定模塊所私有的函數(shù),從而避免可能的名字沖突。
通常使用關(guān)鍵字 extern 來聲明在其他文件中定義的函數(shù)。這一習(xí)慣做法主要是為了程序更清晰,因?yàn)槌呛瘮?shù)聲明使用了關(guān)鍵字 static ,否則認(rèn)為就是extern 的。
總結(jié)
以上是生活随笔為你收集整理的C语言再学习 -- 存储类、链接的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos中使用rpm包或yum命令在
- 下一篇: 元器件基础知识--排阻命名