日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C 预处理指令

發布時間:2023/11/30 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C 预处理指令 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0. Overview

C的預處理指令格式為#name,均以#開頭,#和指令名之間不可有空白字符,#前可以有空字符,但為增強可讀性,一般應從第一列開始

#name不能由宏展開得來,name也不能由宏展開得來,如

// Wrong 1 #define INC #include INC <stdio.h> // Wrong 2 #define INC include #INC <stdio.h>

預處理指令只能占一行,但是在寫代碼時可以用'\'分隔多行,但處理時仍會將這多行合為一行。有些指令帶參數,參數需與指令由空白字符分隔

預處理指令主要提供下列功能:

  • 引入頭文件
  • 宏展開
  • 條件編譯
  • line control:#line(感覺一般人用不著)
  • 診斷(diagnostics):可在編譯器檢查程序,發出errors或warnings

1. 頭文件

用#include來包含頭文件,該指令的參數形式有兩種:

  • #include <file>
    用于系統頭文件。Preprocessor將在a standard list of system directories下搜尋文件file,可以用編譯器的-I選項來將目錄添加到這個list
  • #include "file"
    用于程序自身的頭文件。Preprocessor的搜尋順序如下: a. 先在包含該文件的當前目錄搜尋文件file, b. 然后在quote directories中搜尋,可以用編譯器的-iquote選項來將目錄添加到quote directories中 c. 最后再在用于搜尋<file>的目錄下搜尋(即 1. 中的順序)(所以用#include "stdio.h"只要你不覆蓋這個頭文件的話也不會出現問題,總能找著)
  • #include的參數無論是用""還是<>括起來,都如同一個字符串,里面的注釋不會被識別,宏也不會展開。但是不同于字符串的是,backslash不再有轉義作用,而是一個單純的字符'\'

    在這一行,文件名參數后面除了注釋外不能有任何其他內容

    只包含一次 Once-Only Headers

    如果一個頭文件被include兩次,編譯器就會處理兩次,因此可能會出錯,如重定義等等,標準做法是用所謂的wrapper #ifndef將頭文件的內容包起來,如:

    /* File foo. */ #ifndef FILE_FOO_SEEN #define FILE_FOO_SEENthe entire file#endif /* !FILE_FOO_SEEN */

    代碼片段中的宏FILE_FOO_SEEN叫做controlling macro或者guard macro,在用戶程序頭文件中,該宏的名字不能以_開頭,在系統頭文件中,該宏的名字需要以__(雙下劃線)開頭以免與用戶程序頭文件沖突。在任意類型的頭文件中,該宏的名字應該包含頭文件文件名再加上額外的文字以避免與其他頭文件沖突

    2. 宏 Macros

    宏是賦予名字的一段代碼,每次使用時都將名字替換成宏內容。宏分為兩種,它們在使用時有很大的不同:

  • Object-like macros:使用時像用data objects一樣
  • Function-like macros:使用時像函數調用一樣
  • 2.1 對象形式的宏 Object-like macros

    Object-like macro就是一個簡單的標志符,表示一個代碼片段,在使用時由這個代碼片段來替換,用法:

    #define NAME macro_body

    宏body又叫expansion或replacement list,是一個token序列

    按照慣例,宏的名字一般用大寫字母

    #define macro_body也只占一行,并且macro_body后面不能有其他內容(除空白字符或注釋外),在寫代碼時也可以用'\'分隔多行,但預處理時仍會將它們合為一行

    C preprocessor順序地掃描源程序,因此宏定義只從定義處開始生效

    宏展開是遞歸進行的,preprocessor將一個宏展開后會接著處理展開后的結果,如果這里面有其他的宏,會繼續展開下去。但是如果結果里面再次出現剛剛展開的這個宏的話將不會展開第二次,以免出現無限遞歸的情況

    #define TABLESIZE BUFSIZE #define BUFSIZE 1024 TABLESIZE // -> 先展開為 BUFSIZE // -> 再展開為 1024

    注意雖然宏會展開多次,但是每次的展開過程只是單純地用body替換name,如上面的例子中在展開TABLESIZE時只是單純地用BUFSIZE來替換它,接下來preprocessor才檢查替換結果是不是另一個宏

    2.2 函數形式的宏 Function-like macros

    如其名,這種宏使用起來像函數調用一樣。用法:

    #define name() body

    注意,小括號()必須和宏的名字連在一起,否則會被當成object-like宏來展開,同時,在使用時也必須用name()的形式(此時name和()間可以有空格,2.3中同),只用name的話不會被展開

    2.3 宏參數

    Function-like宏像函數一樣可以接受參數,用法:

    #define name(params_list)

    其中params_list是參數列表,參數必須是有效的C標志符,由,分隔(參數列表中可以出現空格,但是空格沒有實際作用)

    在“調用”函數形式的宏時,將實參列表寫在宏name后面的小括號里,由,分隔,函數形式宏的“調用”不限制在一行內,可以寫成多行,但是參數數量必須和定義時的數量相匹配。可以實參可以是空,但是數量也必須匹配(直白講即逗號數量必須一致),如:

    min(, b) → (( ) < (b) ? ( ) : (b)) min(a, ) → ((a ) < ( ) ? (a ) : ( )) min(,) → (( ) < ( ) ? ( ) : ( )) min((,),) → (((,)) < ( ) ? ((,)) : ( ))min() error→ macro "min" requires 2 arguments, but only 1 given min(,,) error→ macro "min" passed 3 arguments, but takes just 2

    #define min(X, Y) ((X) < (Y) ? (X) : (Y))x = min(a, b); → x = ((a) < (b) ? (a) : (b));y = min(1, 2); → y = ((1) < (2) ? (1) : (2));z = min(a + 28, *p); → z = ((a + 28) < (*p) ? (a + 28) : (*p));

    在展開時會去除各個實參的leading、trailing whitespace,實參的token序列中的whitespace會減成一個空格。在每個實參中,小括號必須平衡,小括號中的逗號不會結束這個參數(即小括號中的逗號不是實參分隔符),但中括號和大括號不要求平衡,而且它們中的逗號會作為實參分隔符截斷這個參數

    宏定義中若參數出現在字符串中,在展開時不會展開成相應實參,如:

    #define foo(x) x, "x" foo(bar) → bar, "x"

    2.4 字符串化 Stringizing

    有時可能需要講宏參數轉換成字符串常量,但是在 2.3 的最后提到字符串中的參數不會被實參替換,為了解決這個問題,可以用預處理操作符#來進行轉換。當參數有一個前導#時,preprocessor會將其替換為實參,再轉換成字符串常量,但是這個過程發生后,被轉換成的字符串中如果還有宏則不會繼續展開,如果還想繼續展開,則需要寫成多級宏的形式,如:

    #define xstr(s) str(s) #define str(s) #s #define foo 4 str (foo)→ "foo" xstr (foo)→ xstr (4)→ str (4)→ "4"

    2.5 拼接

    預處理操作符##用于在宏body中將兩個tokens拼在一起,如A ## B將展開為AB,要求展開后必須是一個有效的C標志符,如一個標志符和數字拼接,兩個數字間的拼接,一些復合操作符如+=的拼接等等,有些拼接是無效的,如x和+。

    拼接常見的應用場景為宏參數間的拼接,如:

    #define COMMAND(NAME) { #NAME, NAME ## _command }struct command commands[] = {COMMAND (quit),COMMAND (help),… };

    2.6 取消宏定義

    #undef name用于取消宏定義,name可以是object-like宏的名字,或者是function-like宏的名字(不用加小括號以及參數列表)

    3. 條件編譯

    3.1 條件編譯常用場景

    • 根據機器架構或操作系統的不同使用不同的代碼
    • 將原文件編譯成兩個不同的程序,其中一個版本可能會用于輸出一些data進行debugging等等
    • 使用#if 0來將排除一段代碼,但將其保留在源文件中用作注釋

    3.2 條件編譯語法

    ifdef,ifndef

    #ifdef MACROcontrolled text#endif /* MACRO */

    if

    #if expressioncontrolled text#endif /* expression */

    expression是一個integer類型的C表達式,可以包含

    • 整形常量
    • 字符常量
    • 數學運算表達式和邏輯運算表達式(遵循短路求值)
    • 宏,在計算宏所代表的表達式前將先展開所有的宏
    • defined預處理指令
    • 所有不是宏的標志符都視為數字0,函數形式的宏但沒有調用實參列表也視為0

    defined

    用在#if和#elif表達式中,用于測試一個名字是否被定義成了一個宏,defined name和defiend ( name )作用相同:如果name定義為了一個宏,則表達式值為1,否則為0,因此#if defined MACRO等價于#ifdef MACRO

    在測試多個宏是否存在時defined比較有用,如:

    #if defined (__vax__) || defined (__ns16000__)

    else

    可以用在#if、#ifdef、#ifndef中

    elif

    elif不需要一個#endif和其匹配

    4. 診斷信息

    • #error導致preprocessor產生一個fatal error,#error所在行的剩余tokens組成錯誤信息
    • #warning導致preprocessor產生一個warning并繼續預處理,#warning所在行的剩余tokens組成錯誤信息

    兩者都不對其參數進行宏展開

    參考

    • GNU - The C Preprocessor: Macros

    轉載于:https://www.cnblogs.com/jerrywossion/p/11071192.html

    總結

    以上是生活随笔為你收集整理的C 预处理指令的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 超碰人人干 | 超碰人人人人 | 亚洲欧美日韩天堂 | 激情文学8888 | 久久久久久av无码免费看大片 | 性感美女在线观看 | 亚洲精品无码成人 | 日韩一级理论片 | 国产精品免费在线播放 | 中文字幕一区二区三区乱码 | 午夜视频一区 | 精品在线观看免费 | 中文精品一区二区三区 | 欧美一级欧美三级 | 亚洲免费av一区 | 91视频网址 | 日本福利片在线观看 | 99在线精品视频免费观看20 | 色花av| 男女午夜视频 | 毛片99| 在线成人国产 | 永久免费AV无码网站韩国毛片 | 精品国产成人亚洲午夜福利 | 色无极亚洲影院 | 久久久久久久久蜜桃 | 丝袜调教91porn| 日韩美女视频网站 | 中文字幕免费在线观看 | 九九热8| 欧洲亚洲一区 | 免费中文字幕在线观看 | 蜜臀久久久久久999 大陆熟妇丰满多毛xxxⅹ | 激情在线观看视频 | 久久人妻免费视频 | 69国产精品视频免费观看 | 久久六六 | 黄色福利社| 黄网在线免费观看 | 亚洲国产成人精品女人久久 | 风间ゆみ大战黑人 | 在线观看日本中文字幕 | 丁香花完整视频在线观看 | 黄网在线观看免费 | 搡老熟女国产 | 男女搞网站 | 女人性高潮视频 | 亚洲伦理自拍 | 最新在线观看av | 欧洲毛片 | 亚洲天堂中文字幕在线观看 | 欧美精品乱码久久久久久 | 黄网站视频在线观看 | 久久免费片 | 日本成人免费在线视频 | 捆绑最紧bdsm视频 | 懂色av一区 | 老司机精品在线 | 欧美视频综合 | 久久亚洲网| 影音先锋男人的天堂 | 亚洲男人天堂2023 | 狠狠干av | 懂色av色吟av夜夜嗨 | 国产成年视频 | 制服.丝袜.亚洲.中文.综合 | 久久国产美女视频 | 顶级黑人搡bbw搡bbbb搡 | 日韩女优一区二区 | 闺蜜张开腿让我爽了一夜 | 免费一级欧美片在线播放 | 国产手机在线播放 | 成人免费毛片观看 | 春草 | 亚洲美女操 | 成人wwxx免费观看 | 国产麻豆剧果冻传媒白晶晶 | jizz中国少妇高潮出水 | 黄色激情视频网站 | 欧美专区日韩专区 | 国产精品jizz在线观看美国 | 欧美三级中文字幕 | 九热视频在线观看 | 在线免费观看污网站 | 亚洲黄色免费电影 | 国产毛片毛片毛片毛片毛片 | 公侵犯人妻一区二区三区 | 五月婷婷丁香在线 | 色中色综合网 | 亚洲一区中文字幕 | 91艹| 奇米精品一区二区三区四区 | 激情免费网站 | 国产传媒国产传媒 | 国产激情自拍 | 天天摸天天干天天操 | 国产精品100 | 久久久一级片 | 亚洲综合国产 |