• <tt id="lutwa"></tt>

    <b id="lutwa"></b>

  • <u id="lutwa"><small id="lutwa"></small></u>
    <b id="lutwa"><small id="lutwa"></small></b>
    
    
    <u id="lutwa"><small id="lutwa"></small></u>
  • <u id="lutwa"><small id="lutwa"></small></u>
    更多課程 選擇中心

    C/C++培訓
    達內IT學院

    400-111-8989

    C語言有哪些關鍵詞,C語言44個關鍵詞大全

    • 發布:C++培訓
    • 來源:學習筆記
    • 時間:2020-05-29 17:12

    目前而言(2017年5月18日) C語言中有 32 + 5 + 7 = 44 個關鍵字. 具體如下

    -> C89關鍵字

    char short int unsigned
    long float double struct
    union void enum signed
    const volatile typedef auto
    register static extern break
    case continue default do
    else for goto if
    return switch while sizeof

    -> C99新增關鍵字

    _Bool _Complex _Imaginary inline restrict

    -> C11新增關鍵字

    _Alignas _Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local

     下面容我細細分析起具體用法.(存在平臺差異, 有問題特別歡迎評論補充, 這就相當于一個關鍵字字典)

     

    C89 32個關鍵字

    1) char

    解釋:

    聲明變量的時候用! char占1字節, 8bit. 多數系統(vs or gcc)上是有符號的(arm 上無符號), 范圍是[-128, 127]. 

    在工程項目開發中推薦用 

    #include <stdint.h>int8_t-> signedcharuint8_t-> unsignedchar

    扯淡一點, 程序開發最長遇到的就是自解釋問題. 雞生蛋, 蛋生雞. 后面再分析 signed 和 unsigned

    演示:

    #include <stdio.h>charc; c=getchar(); rewind(stdin); printf("c = %d, c = %c.\n", c);

     

    2) short

    解釋:

    聲明變量的時候用! short 占2字節, 為無符號的. 默認自帶signed. 范圍[-2^15, 2^15 - 1] 2^15 = 32800.

    推薦使用 int16_t or uint16_t 類型.

    演示:

    shortport =8080; printf("port = %d.\n", port);

     

    3) int

    解釋:

    聲明變量的時候用! int 聲明的變量, 占4字節, 有符號. 范圍 [-2^31, 2^31-1].

    推薦用 int32_t 和 uint32_t類型開發. 方便移植

    演示:

    inthoge =24; printf("hoge = %d.\n", hoge);

     

    4) unsigned

    解釋:

    變量類型修飾符! 被修飾的變量就是無符號的.范圍 >= 0.  unsigned 只能修飾整型的變量.

    當然當你用這個修飾變量的時候. 再使用 - 和 -- 運算的時候一定要小心

    演示:

    unsignedinti =0;//正確unsignedshorts =0;//正確unisgnedfloatf =0.11f;//錯誤

     

    5) long

    解釋:

    聲明變量的時候用!長整型 x86上四字節, x64上8字節. 一定不比int字節數少.  C99之后出現long long類型8字節.

    演示:

    longl =4;longlongll =l; printf("l = %ld, ll = %lld.\n", l, ll);

     

    6) float

    解釋:

    聲明變量的時候用! 四字節. 精度是6-7位左右.  詳細精度可以看 float與double的范圍和精度

    演示:

    floatf = -0.12f;//四字節longfloatlf =0;//八字節 等同于 double, 不推薦這么寫

     

    7) double

    解釋:

    聲明變量的時候用!八字節,精度在15-16位左右.有的時候壓縮內存用float代替.

    演示:

    doubled = 2e13;//8字節longdoubleld = -0.99;//x86也是8字節, 不推薦這么用longlongdoublelld =99;//寫法錯誤, 不支持

     

    8) struct

    解釋:

    定義結構體, 這個關鍵字用法廣泛, 是大頭. c 的重要思路就是面向過程編程. 撐起面向過程的大頭就是結構體.

    struct 就是定義結構的東西, 可以看看下面演示

    演示:

    復制代碼
    //普通結構體定義structnode {intid;structnode *next; };structnode node = {1, NULL };//匿名結構定義struct{intid;char*name; } per= {2,"王志"};
    復制代碼

     

    9) union

    解釋:

    定義公用體, 用法很花哨. 常在特殊庫函數封裝中用到.技巧性強

    演示:

    復制代碼
    //普通定義union type {charc;inti;floatf; }; union type t= { .f =3.33f};//匿名定義union { ... } t ={ .... };//類型匿名定義structcjson {structcjson * next;//采用鏈表結構處理, 放棄二叉樹結構, 優化內存structcjson * child;//type == ( _CJSON_ARRAY or _CJSON_OBJECT ) 那么 child 就不為空unsignedchartype;//數據類型和方式定義, 一個美好的意愿char* key;//json內容那塊的 key名稱union {char* vs;//type == _CJSON_STRING, 是一個字符串doublevd;//type == _CJSON_NUMBER, 是一個num值, ((int)c->vd) 轉成int 或 bool}; };
    復制代碼

    再來一種 union用法, 利用內存對齊. 

    復制代碼
    //12.0 判斷是大端序還是小端序,大端序返回trueinlineboolsh_isbig(void) {staticunion { unsignedshort_s; unsignedchar_c; } _u= {1};return_u._c ==0; }
    復制代碼

    還有很久以前利用union 實現內存字節對齊, 太多了. 每個關鍵字用法, 確實很多, 很意外.

     

    10) void

    解釋:

    這個是空關鍵字. 用法很多. 也是我最喜歡的關鍵字. 用在函數聲明中, 類型定義中.

    演示:

    復制代碼
    //函數聲明externvoidfoo();//函數參數約束externvoidfoo(void);//()中加了void表示函數是無參的, 否則是任意的//萬能類型定義, 指針隨便轉void* arg = NULL;
    復制代碼

     

    11) enum

    解釋:

    枚舉類型, C中枚舉類型很簡陋. 其實就相當于一種變相的INT宏常量. 估計這也許也是 INT宏常量和枚舉并存的原因.

    演示:

    復制代碼
    ////flag_e - 全局操作基本行為返回的枚舉, 用于判斷返回值狀態的狀態碼//>= 0 標識 Success狀態, < 0 標識 Error狀態//typedefenum{ Success_Exist= +2,//希望存在,設置之前已經存在了.Success_Close = +1,//文件描述符讀取關閉, 讀取完畢也會返回這個Success_Base = +0,//結果正確的返回宏Error_Base= -1,//錯誤基類型, 所有錯誤都可用它, 在不清楚的情況下Error_Param = -2,//調用的參數錯誤Error_Alloc = -3,//內存分配錯誤Error_Fd = -4,//文件打開失敗} flag_e;
    復制代碼

    枚舉變量完全可以等同于 int 變量使用, 枚舉值等同于宏INT常量使用. 枚舉的默認值是以1位單位從上向下遞增.

     

    12) signed

    解釋:

    變量聲明類型修飾符. 有符號型, 對比 unsigned 無符號型. 變量聲明默認基本都是 signed, 所以多數別人就省略了.

    演示:

    signedintpiyo =0x1314520; signedchar* str = u8"你好嗎";

    當然了, 平時不需要刻意加. 會讓人嫌麻煩. O(∩_∩)O哈哈~

     

    13) const

    解釋:

    const修飾的變量表示是個不可修改的量. 和常量有點區別. 可以簡單認為 const type val 是個只讀的.

    演示:

    復制代碼
    //聲明不可修改的量constintage =24;//修飾指針constint* pi = NULL;//*pi 不能修改指向變量int*constpt = NULL;//pt 不能指向新的指針constint*constpc = NULL;//*pc 和 pc 都不能動
    復制代碼

    其實在c中基本沒有什么改變不了的. 全是內存來回搞, 軟件不行硬件~~

     

    14) volatile

    解釋:

    聲明變量修飾符, 可變的. 當變量前面有這個修飾符. 編譯器不再從寄存器中取值, 直接內存讀取寫入. 保證實時性.

    常用在多線程代碼中.

    演示:

    復制代碼
    //具體輪詢器structsrl { mq_t mq;//消息隊列pthread_t th;//具體奔跑的線程die_f run;//每個消息都會調用 run(pop())volatileboolloop;//true表示還在繼續};
    復制代碼

    以后使用loop的時候, 其它線程修改, 當前線程也能正確獲取它的值.

     

    15) typedef

    解釋:

    類型重定義修飾符. 重新定義新的類型.

    演示:

    //聲明普通類型typedefvoid*list_t;//聲明不完全類型, 頭文件中不存在struct treetypedefstructtree * tree_t;

     

    16) auto

    解釋:

    變量類型聲明符, auto變量存放在動態存儲區,隨著生命周期{開始 }結束而立即釋放.存放在棧上. 

    默認變量都是auto的. 基本都是不寫, 除非裝逼!

    演示:

    {//生存期開始inthoge =0; autointpiyo =1;//生存期結束}

    不要用生命周期結束的變量, 存在各種意外. 

     

    17) register

    解釋:

    變量修飾符,只能修飾整形變量.表示希望這個變量存放在CPU的寄存器上.現代編譯器在開啟優化時候,

    能夠一定程度上默認啟用register寄存器變量.

    演示:

    復制代碼
    #include <limits.h>register int i = 0; while (i < INT_MAX) {    ++i; }
    復制代碼

    由于CPU寄存器是有限的, 有時候你哪怕聲明的寄存器變量也可能只是普通變量. printf("&i = %p\n", &i) 這種用法是非法.

    寄存器變量不能取地址.

     

    18) static

    解釋:

    static 用法很廣泛. 修飾變量, 表示變量存在于靜態區, 基本就是全局區. 生存周期同系統生存周期.

    static修飾的變量作用域只能在當前文件范圍內. 可以看成上層語言的private. 除了auto就是static.

    static修飾函數表示當前函數是私有的,只能在當前文件中使用. 更加詳細的看演示部分.

    演示:

    復制代碼
    //修飾全局變量, 只對當前文件可見staticint_fd =0;//修飾局部變量, 存儲在全局區, 具有記憶功能{staticint_cnt =0; }//修飾函數, 函數只能在當前文件可見staticvoid* _run(void*arg) { ......returnarg; }////C99之后加的static新用法, 編譯器優化//static 只能修飾函數第一維,表示數組最小長度, 方便編譯器一下取出所有內存進行優化//intsum(inta[static10]) { ... }
    復制代碼

     

    19) extern

    解釋:

    extern 關鍵字表示聲明, 變量聲明, 函數聲明.  奇葩的用法很多.

    演示:

    //聲明引用全局變量externintg_cnt;//聲明引用全局函數externintkill(intsig,intval);

    當然有時候extern不寫, 對于變量不行會出現重定義. 對于函數是可以缺省寫法. 再扯一點

    //extern 主動聲明, 希望外部可以調用externintkill(intsig,intval);//extern 缺省,不推薦外部調用intkill(intsig,intval);

     

    20) break

    解釋:

    結束語句. 主要用于循環的跳轉, 只能跳轉到當前層級. 也用于switch 語句中, 跳出switch嵌套.

    演示:

    復制代碼
    for(;;) {//符合條件跳轉if(six ==6)break; }//break 跳出while循環inti =0;while(i <6) {if(i ==3)break; }
    復制代碼

    break用法主要和循環一塊使用, 還有do while. 但只能跳轉當前層循環. 

     

    21) case

    解釋:

    switch 語句中分支語句. 確定走什么分支.

    演示:

    復制代碼
    //case 普通用法 和 break成對出現switch((c = *++ptr)) {case'b': *nptr++ ='\b';break;case'f': *nptr++ ='\f';break;case'n': *nptr++ ='\n';break;case'r': *nptr++ ='\r';break;case't': *nptr++ ='\t';break; }
    復制代碼

    多扯一點, 對于case相當于標記點. switch 中值決定case跳轉到哪里.再一直往下執行, 遇到break再結束switch嵌套.

     

    22) continue

    解釋:

    跳過此次循環. 直接進行條件判斷操作. for 和 while 有些局別. for 會執行第三個后面的語句.

    演示:

    復制代碼
    //for 循環 continuefor(inti =0; i <20; ++i) {if(i %2==0)continue;//上面continue 調到 ++i -> i < 20 代碼塊}
    復制代碼

     

    23) default

    解釋:

    switch 分支的默認分支, 假如case都沒有進入那就進入default分支. default 可以省略break. c 語法中可行.

    演示:

    復制代碼
    uint32_t skynet_queryname(structskynet_context * context,constchar*name) {switch(name[0]) {case':':returnstrtoul(name+1,NULL,16);case'.':returnskynet_handle_findname(name +1);default: skynet_error(context,"Don't support query global name %s",name); }return0; }
    復制代碼

     

    24) do

    解釋:

    do 循環. 先執行循環體, 后再執行條件判斷.

    演示:

    復制代碼
    register i =0;do{if(i %2==0)continue; printf("i = %d.\n", i); }while(++i <10);
    復制代碼

    do while 循環有時候可以減少一次條件判斷. 性能更好, 代碼更長.

     

    25) else

    解釋:

    else 是 if 的反分支. 具體看演示

    演示:

    復制代碼
    #include <stdbool.h>if(true) { puts("你好嗎?"); }else{ puts("我們分手吧."); }//附贈個else 語法#ifdefined(__GNUC__)//定義了 __GNUC__ 環境, 就是gcc環境#else#error"NOT __GNUC__, NEED GCC!";#enfif
    復制代碼

     

    26) for

    解釋:

    for 循環其實就是while循環的語法糖. 也有獨到的地方.

    演示:

    復制代碼
    for(inti =0; i <2; ++i) {if(i ==1)continue;if(i ==2)break; } 等價于下面這個inti =0;while(i <2) {if(i ==1) {++i;continue; }if(i ==2)break;++i; }//for 最好的寫法, 在于死循環寫法for(;;) {//xxxx}
    復制代碼

    for(;;) {  } 比 while(true) { } 寫法好, 有一種不走條件判斷的意圖, 雖然匯編代碼是一樣的.

     

    27) goto

    解釋:

    goto 是我第二喜歡的關鍵字.  可以在當前函數內跳轉. goto 可以替代所有循環.

    演示:

    __loop://xxx 死循環用法goto__loop; __exitloop:

    還有就是在工程開發中, goto 常用于復制的業務邏輯.

    復制代碼
    if((n = *tar) =='\0')//判斷下一個字符goto__err_ext;if(cl % rl){//檢測 , 號是個數是否正常__err_ext: SL_WARNING("now csv file is illegal! c = %d, n = %d, cl = %d, rl = %d.", c, n, cl, rl);returnfalse; }
    復制代碼

     

    28) if

    解釋:

    if 分支語句. 用法太多了. 程序語句中分支就是智能.

    演示:

    if(false) { puts("我想做個好人!"); }

     

    29) return

    解釋:

    程序返回語句太多了. 用于函數返回中. 返回void 直接 return;

    演示:

    #include <stdlib.h>intmain(intargc,char*argv[]) {returnEXIT_SUCCESS; }

     

    30) switch

    解釋:

    條件分支語句. 很復雜的if else if 時候可以switch.

    演示:

    復制代碼
    #include <unistd.h>do{intrt = write(fd, buf,sizeofbuf)if(rt <0) {switch(errno) {caseEINTERcontinue;default: perror("write error"); } } }while(rt >0);
    復制代碼

     

    31) while

    解釋:

    循環語句, 有do while 和 while 語句兩種.

    演示:

    #define_INT_CNT (10)inti = -1;while(++i <_INT_CNT) {//......}

     

    32) sizeof

    解釋:

    這個關鍵字也稱為 sizeof 運算符. 計算變量或類型的字節大小. 這個關鍵字特別好用!

    演示:

    sizeof(main) ->x86 上四字節// 獲取數組長度,只能是數組類型或""字符串常量,后者包含'\0' #define LEN(arr) (sizeof(arr) / sizeof(*(arr)))

    到這里C89保留的關鍵字基本解釋完畢.

     

    C99 5個新增關鍵字

    33) _Bool

    解釋:

    bool類型變量, 等價于 unsigned char . 只有0和1.

    演示:

    #include <stdbool.h>boolflag =true;//或者直接用_Bool flag = !0;

     

    34) _Complex

    解釋:

    對于C99 標準定義, 存在 float _Complex, double _Complex, long double _Complex 復數類型. 下面先演示gcc 中關于復數的用法.

    演示:

    復制代碼
    #include <math.h>#include<stdio.h>#include<complex.h>////測試 c99 complex 復數//intmain(intargc,char*argv[]) {floatcomplex f = -1.0f+1.0if; printf("The complex number is: %f + %fi\n",crealf(f), cimagf(f));doublecomplex d = csqrt(4.0+4.0i); printf("d = %lf + %lfi\n", creal(d), cimag(d));return0; }
    復制代碼

    其實在復數類型中, gcc標準實現

    #definecomplex _Complex

    而在VS 中實現具體為

    復制代碼
    #ifndef _C_COMPLEX_T#define_C_COMPLEX_Ttypedefstruct_C_double_complex {double_Val[2]; } _C_double_complex; typedefstruct_C_float_complex {float_Val[2]; } _C_float_complex; typedefstruct_C_ldouble_complex {longdouble_Val[2]; } _C_ldouble_complex;#endiftypedef _C_double_complex _Dcomplex; typedef _C_float_complex _Fcomplex; typedef _C_ldouble_complex _Lcomplex;
    復制代碼

    總的而言, 學習C 最好的平臺就是 *nix 平臺上使用 Best new GCC. 當然除了科學計算會用到復數, 其它很少.

    這里VS 和 GCC實現不一樣. 用起來需要注意.

     

    35) _Imaginary

    解釋:

    虛數類型. _Complex 復數類型的虛部. 例如 10.0i, 10.8if 等等.  這個關鍵字在VS 上沒有實現. 其實我也覺得沒有必要.

    和_Complex有重疊.

    演示:

    這個關鍵字無法在代碼中表示. 系統保留, 我們不能使用.

     

    36) inline

    解釋:

    內聯函數,從C++中引入的概念. 就是將小函數直接嵌入到代碼中. C的代碼損耗在于函數的進出棧. 要是可以推薦用內聯函數

    替代宏. 宏能不用就不用. 函數什么的時候不要加inline 需要加extern, 定義的時候需要加inline.

    演示:

    復制代碼
    /** 對json字符串解析返回解析后的結果 * jstr : 待解析的字符串*/externcjson_t cjson_newtstr(tstr_t str); inline cjson_t cjson_newtstr(tstr_t str) { str->len = _cjson_mini(str->str);return_cjson_parse(str->str); }//還有就是和static 一起使用staticinlineint_sconf_acmp(tstr_t tstr,structsconf *rnode) {returnstrcmp(tstr->str, rnode->key); }
    復制代碼

    37) restrict

    解釋:

    這是很裝逼的關鍵字用于編譯器優化. 關鍵字restrict只用于限定指針;該關鍵字用于告知編譯器,

    所有修改該指針所指向內容的操作全部都是基于(base on)該指針的,即不存在其它進行修改操作的途徑;

    這樣的后果是幫助編譯器進行更好的代碼優化,生成更有效率的匯編代碼。

    演示:

    externvoid*mempcpy (void*__restrict __dest,constvoid*__restrict __src, size_t __n) __THROW __nonnull ((1,2));

    上面是摘自GCC 的 string.h中. 其實正式用法

    //簡單演示用法, GCC 和 VS 都是 __restrict 推薦加在 * 后面staticvoid_strlove(char*__restrict dest) {*dest ='\0'; }

    Pelles C 編譯器可以完整支持 restrict.

     

    C11 7個新增關鍵字

    38) _Alignas

    解釋:

    內存對齊的操作符. 需要和_Alignof配合使用, 指定結構的對齊方式.
    演示:

    復制代碼
    #ifndef __cplusplus#definealignas _Alignas#definealignof _Alignof#define__alignas_is_defined 1#define__alignof_is_defined 1#endif
    復制代碼

    例如一種用法

    復制代碼
    #include <stdio.h>#include<stdalign.h>structper {intage;doublesecl;charsex; };intmain(intargc,char*argv[]) {charc[100]; alignas(structper)structper * per = (structper *)&c; printf("per = %p, c = %p.\n", per, c);return0; }
    復制代碼

     

    將c 數組以 struct per 對齊方式對齊返回回去.

     

    39) _Alignof

    解釋:

    得到類型和變量的對齊方式.
    演示:

    printf("alignof(struct per) = %zd.\n", alignof(structper));

     

    40) _Atomic

    解釋:

    原子操作, 原子鎖. gcc 很早就支持. 詳細用法可以參照 CAS https://sanwen8.cn/p/18dZQie.html

    講的可以. 
    演示:

    復制代碼
    #include <stdio.h>#include<stdatomic.h>intmain(intargc,char*argv[]) { _Atomicinthoge = ATOMIC_VAR_INIT(100);intpiyo = atomic_load(&hoge); printf("piyo = %d.\n", piyo); piyo+=2; atomic_store(&hoge, piyo); printf("hoge = %d.\n", hoge);return0; }
    復制代碼

    具體的執行結果, 你也懂就那樣. 原子操作, 對于寫出高效代碼很重要.

     

    41) _Generic

    解釋:

    這個比較叼, C的泛函機制. 高級函數宏. 下面來個老套路用法
    演示:

    復制代碼
    #include <math.h>#include<stdio.h>#include<stdlib.h>#defineABS(x) \_Generic((x),int:abs,float:fabsf,double:fabs)(x)////測試 C11 語法//intmain(intargc,char*argv[]) {inta =1, b =2, c =3; _Generic(a+0.1f,int:b,float:c,default:a)++; printf("a = %d, b = %d, c = %d\n", a, b, c); printf("int abs: %d\n", ABS(-12)); printf("float abs: %f\n", ABS(-12.04f)); printf("double abs: %f\n", ABS(-13.09876));returnEXIT_SUCCESS; }
    復制代碼

    宏泛型真的很給力. 宏又能玩上天了.

     

    42) _Noreturn

    解釋:

    修飾函數,絕對不會有返回值. _Noreturn 聲明的函數不會返回. 引入此新的函數修飾符有兩個目的:

    • 消除編譯器對沒有return的函數的警告. 
    • 允許某種只針對不返回函數的優化.

    演示:

    _Noreturnvoidsuicide(void) { abort();//Actually, abort is _Noreturn as well}

     

    43) _Static_assert

    解釋:

    編譯器期間斷言, 當 #if #error 搞完畢(預編譯)之后, 編譯器斷言. assert是運行時斷言.用的時候看具體的需求.
    演示:

    _Static_assert(__STDC_VERSION__ >=201112L,"C11 support required");//Guess I don't really need _Static_assert to tell me this :-(

     

    44) _Thread_local

    解釋:

    到這里快扯完了, 其實C11標準是個很好的嘗試. 為C引入了線程和原子操作. 各種安全特性補充. 可以說C強大了.

    但是還遠遠不夠, 因為越來越丑了. C11為C引入了線程 在 頭文件<threads.h>中定義.但也允許編譯可以不實現.

    _Thread_local是新的存儲類修飾符, 限定了變量不能在多線程之間共享。
    演示:

    _Thread_localstaticinti;//Thread local isn't local!

    語義上就是線程的私有變量.

    預約申請免費試聽課

    填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

    上一篇:學習C語言知識結構表,C語言基礎知識點盤點
    下一篇:C語言知識結構,C語言學習知識梳理

    C語言創建windows窗口實例

    C++回調函數是什么?

    C++ shared_ptr和動態數組

    C語言有哪些關鍵詞,C語言44個關鍵詞大全

    • 關注微信公眾號

      回復關鍵字:視頻資料

      免費領取 達內課程視頻學習資料

    • 視頻學習QQ群

      添加QQ群:1143617948

      免費領取達內課程視頻學習資料

    Copyright ? 2018 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

    選擇城市和中心
    黑龍江省

    吉林省

    河北省

    湖南省

    貴州省

    云南省

    廣西省

    海南省

    欧美牲交av欧美牲交aⅴ暴力,俄罗斯freeⅹ性欧美,日本加勒比无码中文字幕,放荡的女教师中文字幕