C語言保留字(關鍵字)彙總——轉載

2020-08-13 11:37:02

今天來講講c中的保留字。

保留字(reserved word)

  保留字又稱關鍵字。

  指在高階語言中已經定義過的字,使用者不能再將這些字作爲變數名或過程名使用。

  每種程式設計語言都規定了自己的一套保留字。

  例如:BASIC語言規定不能使用LIST作爲變數名或過程名,因爲LIST是一個BASIC語言專用於顯示記憶體程式的命令。

  C有22+10 = 32個關鍵字

  C++ 有22+10+11+20 = 63 個關鍵字

  JAVA 有22+ 9+ 17 = 48 個關鍵字

ps:以上內容來自百科。


其中,C89中,(C語言標準)中,

型別說明保留字:int,long,short,float,double,char,unsigned,signed,const,void,volatile,enum,struct,union
語句定義保留字:if,else,goto,switch,case,do,while,for,continue,break,return,default,typedef
儲存類說明保留字:auto,register,extern,static
長度運算子保留字:sizeof

具體含義如下:

關鍵字 含義
auto 指定變數的儲存型別,是預設值
break 跳出回圈或switch語句
case 定義switch中的case子句
char 定義字元型變數或指針
const 定義常數或參數
continue 在回圈語句中,回到回圈體的開始處重新執行回圈
default 定義switch中的default子句
do 定義do-while語句
double 定義雙精度浮點數變數
else 條件不滿足的其他情況
enum 定義列舉型別
extern 宣告外部變數或函數
float 定義浮點型變數或指針
for 定義for語句
goto 定義goto語句
if 定義if語句或if-else語句
int 定義整型變數或指針
long 定義長整型變數或指針
register 指定變數的儲存型別是暫存器變數,Turbo c中用自動變數代替
return 從函數返回
short 定義短整型變數或指針
signed 定義有符號的整型變數或指針
sizeof 獲取某種型別的變數或數據所佔記憶體的大小,是運算子
static 指定變數的儲存型別是靜態變數,或指定函數是靜態函數
struct 定義結構體型別
switch 定義switch語句
typedef 爲數據型別定義別名
union 定義無符號的整型或字元型變數或指針
unsigned 定義無符號的整型變數或數據
void 定義空型別變數或空型別指針,或指定函數沒有返回值
volatile 變數的值可能在程式的外部被改變
while 定義while或do-while語句

下面 下麪,就幾個我認爲比較容易用錯的保留字進行分析,主要包括 return, void, const, break, continue

至於儲存類說明保留字,也是難點之一,在之前部落格已經描述過了,這裏就不在重複了。

以下內容參閱《c程式設計競賽實訓教學》和一些大牛部落格結合自己看法寫的。


1.return

return:結束一個函數並返回其後面表達式中的值。

初學的時候,有些不理解main 函數中return 0;有什麼用,在寫程式的時候老是忘記帶上了。其實,帶上return 0;是很有必要的。

main函數的返回值用於說明程式的退出狀態,如果返回0,表示程式正常退出,否則表示程式異常退出。返回值傳遞給程式的啓用者(操作系統)。

如果沒有寫return語句的話,c99(c語言標準)規定編譯器自動在生成的目標檔案中加入return 0;表示正常退出。

所以,爲了程式碼規範,我們一般都必須帶上return 0;


具體操作-----            return (表達式);

其中,括號是可以省略的。 一般不省略,如果返回值爲表示式的時候容易造成混淆。

return返回值的型別,一般是函數定義的型別,如果return後表示式的值型別和函數值的型別不一致,則以函數函數型別爲準,即:函數型別決定返回值型別。

需要注意的一點,也是易錯的一點是:return不能返回指向區域性變數的型別。----因爲在函數結束時區域性變數被自動銷燬(上篇部落格提及的區域性變數的生存週期),則返回的指針爲指向已釋放的空間,再通過此指針進行操作就會產生錯誤。

下面 下麪通過程式具體說明:

  1. #include<stdio.h>
  2. int *test()
  3. {
  4. int num=3,*ptr; //num爲區域性變數
  5. ptr = #
  6. return ptr; //這裏,返回了指向區域性變數的指針
  7. }
  8. int main ( )
  9. {
  10. int i=4,*p;
  11. p = test();
  12. printf("%d,%d\n",i,*p);
  13. return 0;
  14. }

看下輸出結果   4,3

程式中,函數test的返回值爲指向區域性變數num的指針,當主函數呼叫test函數的時候,返回ptr指針並且賦值給p指針變數,即num變數的地址賦給了p,但是必須明白,在test函數結束的時候,區域性變數num的空間被釋放了,這樣用p來參照這個空間就會出錯。

乍一看,和預期的一樣,但是實際上,這樣的程式是存在隱患的。

下面 下麪改改這個程式,就知道錯在哪了。

  1. #include<stdio.h>
  2. int *test()
  3. {
  4. int num=3,*ptr; //num爲區域性變數
  5. ptr = #
  6. return ptr; //這裏,返回了指向區域性變數的指針
  7. }
  8. int test2()
  9. {
  10. int x = 9,y=7;
  11. return (x+y);
  12. }
  13. int main ( )
  14. {
  15. int i=4,*p;
  16. p = test();
  17. i = test2();
  18. printf("%d,%d\n",i,p);
  19. return 0;
  20. }
執行結果:  15,7(也可能是15,9視具體環境而定。)
在這裏,多了個test2函數。發現結果並不是我們預料的15,3 。 p指向空間的數據不是之前num所賦值的3.

這正印證了我們之前說過了,這樣的返回存在隱患。 在test函數呼叫完後,系統釋放之前給num分配的空間,但是p指針仍然指向那塊區域。

在呼叫test2的時候,系統要爲x,y分配空間。這時候就會把之前釋放的那塊空間給x,y再次分配使用,使用在賦值語句後,該空間的值發現了改變,使得p發生了改變。


所以,切記 return不能返回指向區域性變數的型別。


2.void

void :void爲空型別。 void *爲空型別指針。

其中,void a;是不允許的。  每次定義一個變數,系統都會爲其分配空間,而void型別無法確定,系統就不知道該爲它分配多大的空間,顯然是不合理的。

void *p;是允許的,  因爲這是一個指針變數,系統都是預設分配四個位元組的空間,至於具體指向的空間總存放的數據型別,就由使用者自行操作。

並且,在操作的時候,要把該void指針強制轉換爲相應型別的指針後纔可進行操作。

如:

  1. void p;
  2. int a=5,b;
  3. p = &a;
  4. b = (int )p;//強轉爲int型指針。

即:在使用void型別指針變數時,其他型別的地址可以直接賦值給void型別的指針變數,但反過來,void型別的指針變數賦值給其他型別的指針變數或取其所指空間數據時必須進行強轉。


3.const

const:constant的縮寫,意爲不變。 即用const修飾的變數的不允許改變的。也可稱爲只讀變數。

例如:  int const m = 10;   const int m = 10;  (二者可以認爲等價,const定義一般的變數比較簡單。例如該例中都是限定m爲10)

但是要注意一點,只讀變數雖然值不能改變,但它還是變數,不是常數。

如 int const M = 10;  int a[M];  這樣定義陣列是錯誤的。我們知道,定義陣列時,陣列元素個數必須是常數(這樣系統才知道要分配多大的空間),而M的本質是變數,只是值不改變的變數而已。

所以,一般我們定義陣列採用這樣的操作:    #define M 10            int a[M];


下面 下麪討論下const定義指針,這就比較複雜了。

  1. const int p;//const修飾的是p,表示p可變(地址可變),p所指空間的內容不可變(數據不變)
  2. int const p;//const修飾的是p,表示p可變(地址可變),p所指空間的內容不可變(數據不變)
  3. int const p;//const修飾的是p,表示p不可變(地址),p所指空間內容可變(數據可變)
  4. const int const p; //表示p和p所指的空間內容均不可變
至於地址,數據,拿const int p;舉例。   此時,p=&a;操作是允許的,(修改地址)。而p=10;是允許的(試圖改變數據造成錯誤)。


在判讀是修飾p還是p時,我們可以先將定義中的型別識別符號去掉(int),再觀察const後面修飾的內容。


4,break,continue

至於break和continue,二者關係比較密切,結合探討。  break退出當前回圈,continue退出當次回圈

continue
1、結束本次回圈(不執行本次回圈中continue後面的語句),繼續下次回圈條件判斷;
2、不可作用於switch語句。當在switch中使用,這個continue實際是作用於其所屬的回圈結構;若它不屬於任何一個回圈,程式將因此報錯!
break
1、結束整個回圈,並停止下次回圈條件判斷;
2、可以作用於switch語句。
具體區別如下:

break和continue的區別如下: 
1. break可用於switch語句,表示跳出整個switch塊,而continue則不能用於switch語句 
2. 它們都可用於回圈語句的回圈體,所謂的區別也應該是它們對回圈次數的影響不同。break用於立即退出當前回圈,而continue僅跳過當次回圈(本次回圈體內不執行continue語句後的其它語句,但下次回圈還會執行)。舉例說明。 

  1. int i;
  2. int s = 0;
  3. for (int i = 1; i <= 10; i++)
  4. {
  5. if (i == 6) break;
  6. s += i;
  7. }



上面的回圈會因爲break語句而在i=6時提前終止,這樣s的最終值就是1+2+3+4+5 
如將break換成continue 

  1. int i;
  2. int s = 0;
  3. for (int i = 1; i <= 10; i++)
  4. {
  5. if (i == 6) continue;
  6. s += i;
  7. }



當i=6時就不會將i累加到s中,s的最終值是1+2+3+4+5+7+8+9+10,唯獨少一個6