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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux C 预处理详解

發布時間:2023/12/9 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C 预处理详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.預處理程序
按照ANSI標準的定義,預處理程序應該處理以下指令:
#if #ifdef #ifndef #else #elif
#endif
#define
#undef
#line
#error
#pragma
#include
顯然,上述所有的12個預處理指令都以符號#開始,每條預處理指令必須獨占一行。

2.#define
#define指令定義一個標識符和一個串(也就是字符集),在源程序中發現該標識符時,都用該串替換之。這種標識符稱為宏名字,相應的替換稱為宏代換。一般形式如下:
#define macro-name char-sequence
這種語句不用分號結尾。宏名字和串之間可以有多個空白符,但串開始后只能以新行終止。
例如:我們使用LEFT代表1,用RIGHT代表0,我們使用兩個#define指令:
#define LEFT 1
#define RIGHT 0
每當在源程序中遇到LEFT或RIGHT時,編譯程序都用1或0替換。
定義一個宏名字之后,可以在其他宏定義中使用,例如:
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
宏代換就是用相關的串替代標識符。因此,如果希望定義一條標準錯誤信息時,可以如下定義:
#define ERROR_MS “Standard error on input \n”
如果一個串長于一行,可在行尾用反斜線”\”續行,如下:
#define LONG_STRING “This is a very very long \
String that is used as an example” 我們可以用宏寫函數: [cpp]?view plaincopy
  • #define?SWAP(a,b)????\??
  • {????????????????????\??
  • int?temp?=?a;????????\??
  • a?=?b;???????????????\??
  • b?=?temp;????????????\??
  • }????????????????????\???
  • 這里的"\"意為這是條整語句,編譯完成后,函數如果調用了SWAP(a,b),就變成了{int temp = a; a = b;b = temp;}; 宏定義函數與外部調用函數對比: 1)宏定義優點:效率高,因為函數調用涉及壓棧,出棧,而宏定義函數不需要;
    2)宏定義缺點:占空間,因為沒有壓棧和出棧,就會一直占著內存; 宏定義是空間換時間
    3.#error
    #error指令強制編譯程序停止編譯,它主要用于程序調試。#error指令的一般形式是:
    #error error-message
    注意,宏串error-message不用雙引號包圍。遇到#error指令時,錯誤信息被顯示,可能同時還顯示編譯程序作者預先定義的其他內容。
    4.#include ? 文件包含
    程序中的#include指令要求編譯程序讀入另一個源文件。被讀入文件的名字必須用雙引號(“”)或一對尖括號(<>)包圍。 例如:
    #include “stdio.h”
    #include? <stdio.h>
    都使C編譯程序讀入并編譯頭文件以用于I/O系統庫函數。
    包含文件中可以包含其他#include指令,稱為嵌套包含。允許的最大嵌套深度隨編譯器而變。
    文件名被雙括號或尖括號包圍決定了對指定文件的搜索方式: 1)文件名被尖括號包圍時,搜索按編譯程序作者的定義進行,一般用于搜索某些專門放置包含文件的特殊目錄。 2)當文件名被雙括號包圍時,搜索按編譯程序實時的規定進行,一般搜索當前目錄。如未發現,再按尖括號包圍時的辦法重新搜索一次。 我們編譯時也可以加入?gcc -I /home/fs/include??如果我們在當前目錄里找不到"stdio.h",就會到/home/fs/include(這是我們自己存放頭文件的位置)里去搜索,如果還是搜索不到,便會到系統頭文件里去查找; 通常,絕大多數程序員使用尖括號包圍標準的頭文件,雙引號用于包圍與當前程序相關的文件名。 5.?條件編譯指令
    若干編譯指令允許程序員有選擇的編譯程序源代碼的不同部分,這種過程稱為條件編譯。
    5.1#if、#else、#elif #endif
    條件編譯指令中最常用的或許是#if,#else,#elif和#endif。這些指令允許程序員根據常數表達式的結果有條件的包圍部分代碼。
    #if的一般形式是:
    #if constant-expression
    ?Statement sequence
    #endif
    如#if后的常數表達式為真,則#if和#endif中間的代碼被編譯,否則忽略該代碼段。#endif標記#if塊的結束。
    ?
    #else指令的作用與C語言的else相似,#if指令失敗時它可以作為備選指令。例如:
    [cpp]?view plaincopy
  • #include?<stdio.h>???
  • #define?MAX?100??
  • ???
  • Int?main(void)??
  • {??
  • ?#if?MAX?>?99??
  • ????printf(“Compiled?for?array?greater?than?99.\n”);??
  • ?#else??
  • ????printf(“Complied?for?small?array.\n”);??
  • ?#endif??
  • ?return?0;??
  • }??
  • 注意,#else既是標記#if塊的結束,也標記#else塊的開始。因為每個#if只能寫一個#endif匹配。
    ?
    #elif指令的意思是“否則,如果”,為多重編譯選擇建立一條if-else-if(如果-否則-如果鏈)。如果#if表達式為真,該代碼塊被編譯,不測試其他#elif表達式。否則,序列中的下一塊被測試,如果成功則編譯之。一般形式如下:
    #if expression
    ?Statement sequence
    #elif expression1
    ?Statement sequence
    #elif expression2
    ?Statement sequence
    .
    .
    .
    #elif expression
    ?Statement sequence
    #endif?

    5.2#ifdef和#ifndef
    條件編譯的另一個方法是使用編譯指令#ifdef和#ifndef,分別表示“如果已定義”和“如果未定義”。#ifdef的一般形式如下:

    #ifdef?標識符?

    Statement sequence

    #endif

    如果macro-name原先已經被一個#define語句定義,則編譯其中的代碼塊。

    #ifndef的一般形式是:

    #ifndef?標識符

    ?Statement sequence

    #endif

    如果macro-name當前未被#define語句定義,則編譯其中的代碼塊。
    #ifdef和#ifndef都可以使用#else或#elif語句。

    [cpp]?view plaincopy
  • #inlucde?<stdio.h>???
  • #define?T?10??
  • ???
  • Int?main(void)??
  • {??
  • ?#ifdef?t??
  • ????printf(“Hi?T\n”);??
  • ?#else??
  • ????printf(“Hi?anyone\n”);??
  • ?#endif??
  • ?#ifndef?M??
  • ????printf(“M?Not?Defined\n”);??
  • ?#endif??
  • ???
  • ?Return?0;??
  • }??
  • 6.#undef
    #undef指令刪除前面定義的宏名字。也就是說,它“不定義”宏。一般形式為:
    #undef macro-name


    7.?#defined
    除#ifdef之外,還有另外一種確定是否定義宏名字的方法,即可以將#if指令與defined編譯時操作符一起使用。defined操作符的一般形式如下:
    defined macro-name
    如果macro-name是當前定義的,則表達式為真,否則為假。
    例如,確定宏MY是否定義,可以使用下列兩種預處理命令之一:
    #if defined MY

    #ifdef MY
    也可以在defined之前加上感嘆號”!”來反轉相應的條件。例如,只有在DEBUG未定義的情況下才編譯。
    #if !defined DEBUG
    ?Printf(“Final Version!\n”);
    #endif
    使用defined的一個原因是,它允許由#elif語句確定的宏名字存在。


    8.#line
    #line指令改變__LINE__和__FILE__的內容。__LINE__和__FILE__都是編譯程序中預定義的標識符。標識符__LINE__的內容是當前被編譯代碼行的行號,__FILE__的內容是當前被編譯源文件的文件名。#line的一般形式是:
    #line number “filename”
    其中,number是正整數并變成__LINE__的新值;可選的“filename”是合法文件標識符并變成__FILE__的新值。#line主要用于調試和特殊應用。

    9.#pragma
    #pragma是編譯程序實現時定義的指令,它允許由此向編譯程序傳入各種指令。例如,一個編譯程序可能具有支持跟蹤程序執行的選項,此時可以用#pragma語句選擇該功能。編譯程序忽略其不支持的#pragma選項。#pragma提高C源程序對編譯程序的可移植性。


    10. 預處理操作符#和##
    有兩個預處理操作符:#和##,它們可以在#define中使用。
    操作符#通常稱為字符串化的操作符,它把其后的串變成用雙引號包圍的串。例如:

    [cpp]?view plaincopy
  • #include?<stdio.h>???
  • #define?mkstr(s)?#s??
  • int?main(void)??
  • {??
  • ????p(mkstr(I?like?C));??
  • ???
  • ????Return?0;??
  • }??
  • 預處理程序把以下的語句:
    Printf(mkstr(I like C));
    變成
    Printf(“I like C”);
    操作符##把兩個標記拼在一起,形成一個新標記。例如:

    [cpp]?view plaincopy
  • #include?<stdio.h>???
  • #define?concat(a,a)?a##b??
  • ???
  • int?main(void)??
  • {??
  • ?Int?xy?=?10;??
  • ?Printf(“%d”,concat(x,y));??
  • ?Return?0;??
  • }??
  • 預處理程序把以下語句:
    Printf(“%d”,concat(x,y));
    變成
    Printf(“%d”,xy);
    操作符#和##主要作用是允許預處理程序對付某些特殊情況,多數程序中并不需要。


    11. 預定義宏
    C規范了5個固有的預定義宏,它們是:
    __LINE__
    __FILE__
    __DATE__
    __TIME__
    __STDC__
    ?
    __LINE__和__FILE__包含正在編譯的程序的行號和文件名。
    __DATE__和內容形如month/day/year(月/日/年)的串,代表源文件翻譯成目標碼的日期。
    __TIME__中的串代表源代碼編譯成目標碼的時間,形如hour:minute:second(時:分:秒)
    如果__STDC__的內容是十進制常數1,則表示編譯程序的實現符合標準C。

    附: 在預處理中,我們經常用到define ,這里得提到 typedef ,二者用法很相似,大家還不要搞混;具體的區別是什么呢? 1、typedef 是C語言關鍵字 2、define 是預處理命令 這里介紹一下typedef的應用,typedef經常被用于為另一種數據類型定義一個新名字,在數據結構中更是頻繁出現 typedef <已有數據類型> <新數據類型> 下面舉個例子介紹: [cpp]?view plaincopy
  • typedef?struct?_node_??
  • {??
  • ????int?data;??
  • ????struct?_node_?*next;??
  • }listnode,*linklist;??
  • 這里定義了兩個新的數據類型listnode和linklist。其中listnode等價于數據類型struct _node_ 而linklist等價于stuct _node_? *; 或者,我們這樣理解,上面的定義就相當于: [cpp]?view plaincopy
  • struct?_node_??
  • {??
  • ????int?data;??
  • ????struct?_node_?*next;??
  • };??
  • typedef?struct?_node_?listnode;??
  • typedef?struct?_node_?*linklist;?
  • 總結

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

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