<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
大家好,我是努力學習游泳的魚。關鍵字,這名字一聽,就很關鍵。而有些關鍵字,你可能不是很瞭解,更別談使用。所以,這篇文章將帶你見識常見的關鍵字,一起領略它們的風采吧。
C語言提供了豐富的關鍵字,這些關鍵字都是語言本身預先設定好的,
使用者自己是不能創造關鍵字的。
大部分關鍵字會在其他章節介紹,這裡僅介紹一些稍微有點難度的關鍵字。
extern可以用來宣告外部符號,如外部的全域性變數和函數。
如我們在test1.c裡定義了全域性變數aint a = 2022;
我們想在test2.c裡使用,就得先用extern宣告一下extern int a;
注意:一般extern是用來宣告外部的全域性變數的。因為如果直接寫int a;就不是宣告了,而是定義,會直接建立一個變數a。只有寫extern int a;才是宣告變數a。如果是宣告外部的函數,可以省略掉extern。如直接寫int Add(int, int);和寫extern int Add(int, int);效果是相同的。
C語言裡的區域性變數,進入區域性範圍時自動建立,出區域性範圍時自動銷燬。這種自動建立,自動銷燬的特性,其實是由於前面省略了關鍵字auto。比如,int a = 0;其實編譯器會處理為auto int a = 0;一般來說,auto會被省略掉。
typedef關鍵字用於給型別起別名,相當於起了個外號。
比如unsigned int num = 10;如果我們嫌unsigned int這個型別寫起來太麻煩了,可以給它起個別名叫做uint:typedef unsigned int uint;這樣上面的程式碼就等價於uint num = 10;
資料的儲存,需要記憶體。常見的記憶體有:
網路硬碟,硬碟,記憶體,高階快取,暫存器。
從左到右,速度越快,從而造價越高,從而空間越小。
早期,CPU處理的資料都來自記憶體。當時,CPU的處理速度和記憶體的讀寫速度是差不多的。隨著技術的迭代,記憶體的讀寫速度逐漸跟不上CPU的處理速度,CPU在很大程度上被閒置了。
於是就有了這麼一層設計。在記憶體之上設定讀寫速度更快的高階快取和暫存器。CPU從暫存器中拿資料,與此同時,暫存器從高階快取中拿資料,高階快取從記憶體中拿資料。如果CPU想要的資料在暫存器中沒有,那就直接從高階快取中拿資料,如果還沒有再從記憶體中拿。由於大部分資料都能在暫存器中命中,整體上,處理資料的速度就提升了。
以上,我們能明白一點:
暫存器的讀寫速度是非常快的!
如果我們寫int num = 10;num是放在記憶體中的。如果我們加了個registerregister int num = 10;此時register的作用是建議把num放在暫存器中。注意只是建議,實際是否放在暫存器中取決於編譯器的處理。
在C語言中,static有3種用法,分別修飾區域性變數,全域性變數和函數。
1.修飾區域性變數-稱為靜態區域性變數
2.修飾全域性變數-稱為靜態全域性變數
3.修飾函數-稱為靜態函數
7.1.1 程式碼對比
下面程式碼的輸出結果是多少呢?
#include <stdio.h> void test() { int a = 5; a++; printf("%d ", a); } int main() { int i = 0; while (i < 10) { test(); i++; } return 0; }
輸出結果:
10個6
為什麼呢?test函數被呼叫了10次,每次都做了同樣一件事,建立a並初始化為5,a自增變成6,列印a(即6)。本質上,每次進入test函數都會建立a,出test函數時都會銷燬a。這是由於區域性變數的特性:進入區域性範圍建立,出區域性範圍銷燬。那麼,每次進入test函數建立的都是一個新的a,和之前建立的a沒有任何關係。
明白這點後,再看下面這段程式碼,輸出的結果又是多少?
#include <stdio.h> void test() { static int a = 5; a++; printf("%d ", a); } int main() { int i = 0; while (i < 10) { test(); i++; } return 0; }
答案:
輸出6~15。
分析一下:第一次呼叫test函數時和沒有static相同,建立a並初始化,自增,列印(此時a是6),但第二次呼叫怎麼就列印7了呢?這說明,第二次呼叫時,a還是上次呼叫留下來的6,才會自增變成7!也就是說,第一次呼叫結束後,a並沒有銷燬,第二次呼叫時依然存在。同理,第二次呼叫後a也沒有銷燬,第三次呼叫時a仍是第二次呼叫留下來的7,然後自增變成8後列印,以此類推。
static修飾區域性變數的時候,區域性變數就變成了靜態的區域性變數,出了區域性的範圍,不會銷燬,下一次進入函數依然存在。
7.1.2 原理分析
記憶體可以分為:棧區,堆區,靜態區,等等。
棧區儲存的是區域性變數,函數引數,等等。
堆區是用來動態記憶體開闢的,與之相關的函數有malloc,realloc,calloc和free等等。
靜態區儲存的是靜態變數和全域性變數。
靜態的區域性變數出了作用域依然存在,是因為它是儲存在靜態區的。
同樣儲存在靜態區的全域性變數,生命週期也很長。
static修飾區域性變數時,實際改變的是變數的儲存位置,本來一個區域性變數是放在棧區的,被static修飾後放在了靜態區,從而導致,出了作用域依然存在,生命週期並沒有結束。
注意:放在靜態區的變數出了作用域不銷燬,相當於生命週期變長了,但是作用域並沒有發生變化,也就是說,靜態的區域性變數仍然只能在它的區域性範圍內使用!
靜態區中的資料的生命週期和程式的生命週期是一致的。程式結束,靜態資料的生命週期也就到了。
7.2.1 程式碼對比
我們建立兩個原始檔,test1.c和test2.c
在test1.c裡定義一個全域性變數g_val
// test1.c int g_val = 2022; // 全域性變數,定義在test1.c中
在test2.c內部使用這個全域性變數,由於全域性變數的作用域是整個工程,所以可以跨原始檔使用。但是在使用前需要使用extern宣告,否則會報編譯錯誤。
// test2.c extern int g_val; int main() { g_val = 2023; return 0; }
如果我們在g_val的定義前面加上static會發生什麼呢?
// test1.c static int g_val = 2022; // 全域性變數,定義在test1.c中 // test2.c extern int g_val; int main() { g_val = 2023; return 0; }
此時會報連結錯誤,因為g_val是定義在test1.c裡的靜態全域性變數,不能在test2.c內部使用。看來靜態的全域性變數不能跨檔案使用了。
7.2.2 原理分析
一個全域性變數本來是具有外部連結屬性的,既能在自己所在的原始檔內部使用,也能在其他檔案內部使用。
但是被static修飾之後外部連結屬性就變成了內部連結屬性,只能在自己所在的原始檔內部使用,不能在其他檔案內部使用了。
使用上感覺作用域變小了。
7.3.1 程式碼對比
我們在test1.c裡定義一個函數
// test1.c int Add(int x, int y) { return x + y; }
在test2.c內部使用,同理要先宣告(此時可以省略extern),否則會報一個警告。
// test2.c #include <stdio.h> extern int Add(int, int); // extern可以省略 int main() { int sum = Add(10, 20); printf("sum = %dn", sum); return 0; }
如果在函數定義前加上static會發生什麼呢?
// test1.c static int Add(int x, int y) { return x + y; } // test2.c #include <stdio.h> extern int Add(int, int); // extern可以省略 int main() { int sum = Add(10, 20); printf("sum = %dn", sum); return 0; }
此時會報連結錯誤,因為Add函數是定義在test1.c內部的靜態函數,不能在test2.c內部使用。看來static修飾函數和修飾全域性變數類似,靜態的函數也不能跨檔案呼叫。
7.3.2 原理分析
static修飾函數的作用:一個函數本來是具有外部連結屬性的,但是被static修飾之後,外部連結屬性就變成了內部連結屬性,這時這個函數只能在自己所在的原始檔內部使用,其他檔案是無法使用的。
使用上的感覺好像是作用域變小了。
到此這篇關於C語言學習之關鍵字的範例詳解的文章就介紹到這了,更多相關C語言關鍵字內容請搜尋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