<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在解釋 auto 之前,先來了解一下什麼是區域性變數。
在很多印象中,對區域性變數的描述是:函數內定義的變數稱為區域性變數。並且下面這段程式碼也很好的解釋了這句話:
#include <stdio.h> void print() { int a = 10; printf("%d", a); } int main() { print(); printf("%d", a); return 0; }
顯然這段程式碼是錯的,編譯器也會報錯:
但事實上 “函數內部定義的變數是區域性變數” 這種說法是不錯的,但是不準確。我們來看這樣一段程式碼:
#include <stdio.h> int main() { int func = 10; if (func) { int num = 1; } printf("%d", num); return 0; }
同樣編譯器也會報錯:
所以正確的理解應該是:在 { } 中定義的變數叫做區域性變數。
那麼我們順水推舟提一個問題:區域性變數與我們的關鍵字 auto 有什麼聯絡?
其實在早期的C語言中,區域性變數是需要用 auto 修飾的,但現在的編譯器發展越來越智慧,會自動識別哪個變數是區域性變數。所以,現在對於區域性變數的 auto 關鍵字都是省略的。
我們可用這段程式碼證明:
#include <stdio.h> void print() { auto int a = 10; printf("%dn", a); } int main() { int a = 10; printf("%dn", a); print(); return 0; }
所以對於 auto 這個關鍵字來說,只需瞭解、知道就好。
千萬不能把這個單詞翻譯成:登記、註冊!正確的翻譯應該是:暫存器。
那暫存器是什麼?暫存器是計算機 CPU 的一組硬體,存在的本質是提高計算機的執行效率,因為暫存器不需要從記憶體中拿資料。也就是說把資料直接放在暫存器,直接供 CPU 計算,從而提升執行效率。
所以我們大膽猜測:register 修飾的變數,意義在於儘量把修飾的變數放入 CPU 暫存器中。
那麼什麼樣的變數適合用 register 來修飾呢?
我們通過程式碼來闡述如何使用這個關鍵字:
#include <stdio.h> int main() { register num = 10; int sum = 0; int i = 0; for (i = 0; i < 10; i++) { sum += num+i; } printf("%dn", sum); return 0; }
這段程式碼完美符合了適合使用 register 修飾的變數的三個條件,雖然規模又億些小,演演算法有億些簡單。num 變數是區域性變數,並且接下來的程式碼沒有對其進行寫入,並且重複使用了 10 次。
如果我們寫了 200000 個區域性變數,並且所有的區域性變數都用 register 來修飾,那麼編譯器會不會因為暫存器不夠用而報錯?我認為不會,因為 register 的定義是儘量把變數放入暫存器中。
對於 static 這個關鍵字,一般應用於多檔案操作中,這是因為有利於專案維護、提供安全保證。
那麼對於多檔案操作不是本篇的內容,我會在另外一篇單獨寫一篇關於這塊的內容。
那麼 stactic 可以修飾的物件有三個:
我們先觀察全域性變數沒有被 static 修飾的時候的效果:
我們在 test.c 檔案中定義全域性變數:
//test.c int num = 10;
在 test.h 檔案中對此宣告:
//test.h #pragram once #include <stdio.h> extern int num;
在 main.c 檔案中使用此變數:
//main.c #include "test.h" int main() { printf("%dn", num); return 0; }
執行結果:
現在我們來觀察當全域性變數被 static 修飾的時候會發生什麼:
在 test.c 下使用 static 修飾全域性變數,其他檔案不變:
//test.c static int num = 10;
執行結果:
可以看到這個程式在連結時出現了錯誤,即 num 變數“消失”了一樣。那麼這種“消失”恰恰是 static 的魅力所在。
結論一:對於 static 修飾的全域性變數,該變數就變為只能在本檔案中使用,不能被其他檔案直接使用。
但是要注意,僅僅是不能被直接使用,我們通過間接存取,程式還是可以執行的:
我們在 test.c 中定義一個函數:
//test.c #include "test.h" static int num = 10; void print() { printf("%dn", num); }
test.h 檔案中宣告 print 函數:
//test.h #pragma once #include <stdio.h> extern int num; void print();
在 main.c 檔案中我們這樣做:
//main.c #include "test.h" int main() { //printf("%dn", num); print(); return 0; }
那麼執行的效果:
上面這種情況我們可以把它視為 static 沒有修飾 print 函數的情況。所以現在我們來討論 static 修飾函數時候的情況:
在 test.c 檔案中修飾 print 函數:
//test.c #include "test.h" int num = 10; static void print() { printf("%dn", num); }
test.h 、main.c 檔案不變,執行結果為:
可以看到函數被 static 修飾的效果與 全域性變數變數被 static 修飾的時候一致,那麼我們不難得出下面的結論:
結論二:當 static 修飾函數時,此函數只能在本檔案內使用,不能被其他檔案直接存取。
同理,我們可以修改程式碼來達到間接存取:
我們在 test.c 中多寫一個函數:
//test.c #include "test.h" int num = 10; static void print() { printf("%dn", num); } void func() { print(); }
在 test.h 中對此函數進行宣告:
//test.h #pragma once #include <stdio.h> extern int num; void print(); void func();
在 main.c 中呼叫:
//main.c #include "test.h" int main() { //printf("%dn", num); //print(); func(); return 0; }
執行結果:
現在,我們觀察區域性變數沒有被 static 修飾的時候的一段程式碼:
#include <stdio.h> void test() { int i = 0; i++; printf("%dn", i); } int main() { for (int i = 0; i < 10; i++) { test(); } return 0; }
那麼它的輸出結果是:
很明顯,超出了我們的預期。我們的預期是輸出 1,2,3,4,5,6,7,8,9,10 。為什麼輸出 10 次輸出的都是 1 呢?對於區域性變數來說,生命週期在 { } 中定義開始,在出 { } 時結束。也就是說,在 { } 中定義的區域性變數在記憶體中開闢了一塊空間,在出 { } 時開闢的空間釋放(銷燬)。
那有什麼辦法能使空間不被釋放呢?有,那就是用 static 修飾區域性變數:
#include <stdio.h> void test() { static int i = 0; i++; printf("%dn", i); } int main() { for (int i = 0; i < 10; i++) { test(); } return 0; }
輸出的結果是:
那麼為什麼會輸出這樣的結果呢?從上面的結果分析我們知道了區域性變數的生命週期,我們只要改變區域性變數的生命週期就能夠解決問題。也就是說,static 修飾的區域性變數,能夠讓其原本儲存在棧區而讓其儲存到靜態區,只能被定義一次(對於任何變數來說都是這樣,只不過我們的重點在於改變變數的生命週期)從而達到修改生命週期的作用。
結論三:static 修飾區域性變數,能夠讓其生命週期從區域性週期變為全域性週期。
到此這篇關於C語言關鍵字auto與register及static專項詳解的文章就介紹到這了,更多相關C語言 auto register static內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45