99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C/C++預(yù)處理命令的工作原理及分類

CHANBAEK ? 來源:明解嵌入式 ? 作者:Sharemaker001 ? 2023-04-15 11:32 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

摘要:在C/C++語言編程過程中,經(jīng)常會(huì)用到如#include、#define等指令,同時(shí)也會(huì)涉及到大量的預(yù)處理與條件編譯,這樣做的好處可以使代碼更利于移植移植性,也讓代碼易于修改。 因此引入了預(yù)處理與條件編譯的概念。

預(yù)處理的行為是由指令控制的。 所有的預(yù)處理器命令都是以#開頭,它必須是第一個(gè)非空字符。 預(yù)處理指令由預(yù)處理程序(預(yù)處理器)操作。

預(yù)處理器不是編譯器的組成部分,但是它是編譯過程中一個(gè)單獨(dú)的步驟。 因此, 預(yù)處理器只不過是一個(gè)文本替換工具而已,它們會(huì)指示編譯器在實(shí)際編譯之前完成所需的預(yù)處理。 通俗來講預(yù)處理命令的作用就是在編譯和鏈接之前,對(duì)源文件進(jìn)行一些文本方面的操作,比如文本替換、文件包含、刪除部分代碼等,這個(gè)過程叫做預(yù)處理(在編譯之前對(duì)源文件進(jìn)行簡單加工)

相比其他編程語言,C/C++語言更依賴預(yù)處理器,故在閱讀或開發(fā)C/C++程序過程中,可能會(huì)接觸大量的預(yù)處理指令。 預(yù)處理指令不屬于C/C++語言的語法,但在一定意義上可以說預(yù)處理擴(kuò)展了C/C++。 預(yù)處理命令的分類主要?jiǎng)澐譃橐韵聨追N類型:

1、宏定義

#define命令并不是真正的定義符號(hào)常量,而是定義一個(gè)可以替換的宏。 被定義為宏的標(biāo)示符稱為“宏名”。 在編譯預(yù)處理過程時(shí),對(duì)程序中所有出現(xiàn)的“宏名”,都用宏定義中的字符串去代換,這稱為“宏代換”或“宏展開”。 宏替換在編譯前進(jìn)行,不分配內(nèi)存; 宏展開不占運(yùn)行時(shí)間,只占編譯時(shí)間; 宏替換只作替換,不做計(jì)算。

#define NEMBER 9 //#define 宏名 文本
#define M(a, b) a*b //#define 宏名(參數(shù)表) 文本
#define SWITCHON  //#define 宏名  //(定義一個(gè)條件編譯的開關(guān)字段)
#define NAME(n) num ## n   //宏定義,使用 ## 運(yùn)算符,粘合的作用
int num0 = 10;
printf("num0 = %d\\n", NAME(0));//宏調(diào)用NAME(0)被替換為 num ## 0,被粘合為:num0
//可變宏:… 和 __VA_ARGS__
#define PR(...) printf(__VA_ARGS__)     //宏定義
PR("hello\\n");                          //宏調(diào)用
//輸出結(jié)果:hello
//在宏定義中,形參列表的最后一個(gè)參數(shù)為省略號(hào)“…”,而“__VA_ARGS__”就可以被用在替換文本中,來表示省略號(hào)“…”代表了什么。
//而上面例子宏代換之后為:printf(“hello\\n”);

#undef指令刪除前面定義的宏名字(也就是#define的標(biāo)識(shí)符)。 也就是說,它“不定義”宏。 (注意:如果標(biāo)識(shí)符當(dāng)前沒有被定義成一個(gè)宏名稱,那么就會(huì)忽略該指令),一般形式為:

#undef  NEMBER      //取消之前已定義的NEMBER
#define NEMBER 100  //重新定義NUMBE為100

2、系統(tǒng)預(yù)定義的宏

LINE : 當(dāng)前源文件的行號(hào),整數(shù)

FILE : 當(dāng)前源文件名,char 字符串,文件的完整路徑和文件名**

DATE : 當(dāng)前編譯日期,char 字符串,格式:月 日 年

TIME : 當(dāng)前編譯時(shí)間,char 字符串,格式:時(shí) 分 秒

STDC : 整數(shù) 1,表示兼容 ANSI/ISO C 標(biāo)準(zhǔn),配合 #if 使用

**TIMESTAMP ** : 最后一次修改當(dāng)前文件的時(shí)間戳,char 字符串,格式:年 月份 日期 時(shí) 分 秒

3、文件包含

當(dāng)一個(gè)C語言程序由多個(gè)文件模塊組成時(shí),主模塊中一般包含main函數(shù)和一些當(dāng)前程序?qū)S玫暮瘮?shù)。 程序從main函數(shù)開始執(zhí)行,在執(zhí)行過程中,可調(diào)用當(dāng)前文件中的函數(shù),也可調(diào)用其他文件模塊中的函數(shù)。

如果在模塊中要調(diào)用其他文件模塊中的函數(shù),首先必須在主模塊中聲明該函數(shù)原型。 一般都是采用文件包含的方法,包含其他文件模塊的頭文件。

包含文件的格式有#include后面跟尖括號(hào)<>和雙引號(hào)“”之分。 兩者的主要差別是搜索路徑的不同。 C的標(biāo)準(zhǔn)庫加.h,C++標(biāo)準(zhǔn)庫可以不加.h。

尖括號(hào)形式:如#include

雙引號(hào)形式:如#include“para.h”,首先到當(dāng)前工作目錄下查找該文件,如果未發(fā)現(xiàn),再按尖括號(hào)包含時(shí)的辦法到系統(tǒng)目錄下查找。 包含自定義的頭文件,一般采用該方式。 雖然系統(tǒng)標(biāo)準(zhǔn)庫頭文件采用此方式也正確,但浪費(fèi)了不必要的搜索時(shí)間,故系統(tǒng)標(biāo)準(zhǔn)庫頭文件不建議采用該包含方式。

4、條件編譯

條件編譯允許程序員有選擇按照不同的條件去編譯程序的不同部分,從而得到不同的目標(biāo)代碼。 使用條件編譯,可方便地處理程序的調(diào)試版本和正式版本,也可使用條件編譯使程序的移植更方便。

常見的條件編譯指令有 #if、#elif、#else、#endif、#ifdef、#ifndef。

#if、#elif、#else、#endif的使用和if、elseif 、else的使用非常相似,一般使用格式如下:

#if 整型常量表達(dá)式1
    程序段1
#elif 整型常量表達(dá)式2
    程序段2
#else
    程序段3
#endif

執(zhí)行起來就是,如果整形常量表達(dá)式為真,則執(zhí)行程序段1,否則繼續(xù)往后判斷依次類推(注意是整形常量表達(dá)式),最后#endif是#if的結(jié)束標(biāo)志。

#ifdef的作用是判斷某個(gè)宏是否定義,如果該宏已經(jīng)定義則執(zhí)行后面的代碼,#ifndef恰好和#ifdef相反,一般使用格式如下:

//ifdef
#ifdef  宏名
    程序段1
#else
    程序段2
#endif
//ifndef
#ifndef 宏名
    程序段1 
#else 
    程序段2 
#endif

#ifdef表示如果該宏已被定義過,則對(duì)“程序段1”進(jìn)行編譯,否則對(duì)“程序段2”進(jìn)行編譯(這個(gè)和上面的#if一樣最后都需要#endif),上述格式也可以不用#else,這一點(diǎn)上和if else相同。

#ifndef表示如果該宏未被定義,則對(duì)“程序段1”進(jìn)行編譯,否則對(duì)“程序段2”進(jìn)行編譯。

5、特殊命令

#line 可以改變 LINE 和 _FILE_兩個(gè)宏的內(nèi)容,即為其指定新的值。 其本質(zhì)是重定義 LINEFILE ,主要有以下兩種形式:

#line linenum

#line linenum 文件名

int main()
{
   printf( "code is on line %d, in file %s\\n", __LINE__, __FILE__ );
#line 10
   printf( "code is on line %d, in file %s\\n", __LINE__, __FILE__ );
#line 20 "hello.cpp"
   printf( "code is on line %d, in file %s\\n", __LINE__, __FILE__ );
   printf( "code is on line %d, in file %s\\n", __LINE__, __FILE__ );
}

輸出為:

code is on line 7, in file line_directive.cpp
code is on line 10, in file line_directive.cpp
code is on line 20, in file hello.cpp
code is on line 21, in file hello.cpp

#error :當(dāng)預(yù)處理器預(yù)處理到#error命令時(shí)將停止編譯并輸出用戶自定義的錯(cuò)誤消息,一般用于調(diào)試程序。

#error [用戶自定義的錯(cuò)誤消息]
//注:上述語法成份中的方括號(hào)"[]"代表用戶自定義的錯(cuò)誤消息可以省略不寫。
//舉例1:
#error Sorry,an error has occurred!
//舉例2: 
#error


#ifndef A
    #define A 5
#endif

#if A < 5
    #error Sorry,an error has occurred!
#endif

#warning :****類似于#error 指令,但不會(huì)導(dǎo)致取消預(yù)處理,程序繼續(xù)編譯,不會(huì)影響程序的正常運(yùn)行。 #warning 指令之后的信息在預(yù)處理繼續(xù)之前作為消息輸出,產(chǎn)生警告。

#warning [用戶自定義的警告信息]
#warning Sorry,an warning has occurred!

#pragma:是功能比較豐富且靈活的指令,可以有不同的參數(shù)選擇,從而完成相應(yīng)的特 定功能操作。 #pragma指令是計(jì)算機(jī)或操作系統(tǒng)特定的,并且通常對(duì)于每個(gè)編譯器而言都有所不同。 #pragma指令可用于條件語句以提供新的預(yù)處理器功能,或?yàn)榫幾g器提供實(shí)現(xiàn)所定義的信息

其格式一般為: #pragma Para。 其中Para 為參數(shù),參數(shù)可以有 message 類型、code_seg、once、warning、pack 等,具體可以在網(wǎng)上詳細(xì)查看。 舉兩個(gè)常用的例子:

#pragma一次

只要在頭文件的最開始加入這條指令就能夠保證指定該文件在編譯源代碼文件時(shí)僅由編譯器包含(打開)一次,使用 #pragma once 可減少生成次數(shù),和使用預(yù)處理宏定義來避免多次包含文件的內(nèi)容的效果是一樣的,但是需要鍵入的代碼少,可減少錯(cuò)誤率,這條指令實(shí)際上在VC6中就已經(jīng)有了,但是考慮到兼容性并沒有太多的使用它。

//使用#progma once
#pragma once  
// Code placed here is included only once per translation unit 


//使用宏定義方式
#ifndef HEADER_H_ 
#define HEADER_H_  
// Code placed here is included only once per translation unit  
#endif // HEADER_H_

#pragma once是編譯相關(guān),就是說這個(gè)編譯系統(tǒng)上能用,但在其他編譯系統(tǒng)不一定可以,也就是說移植性差,不過基本上已經(jīng)是每個(gè)編譯器都有這個(gè)定義了。

#pragma包 (n)

指定結(jié)構(gòu)、聯(lián)合和類成員的封裝對(duì)齊。 其實(shí)就是改變編譯器的內(nèi)存對(duì)齊方式。 這個(gè)功能對(duì)于集合數(shù)據(jù)體使用,默認(rèn)的數(shù)據(jù)的對(duì)齊方式占用內(nèi)存比較大,可進(jìn)行修改。 在沒有參數(shù)的情況下調(diào)用pack會(huì)將n設(shè)置為編譯器選項(xiàng)中設(shè)置的值。 如果未設(shè)置編譯器選項(xiàng),windows默認(rèn)為8,linux默認(rèn)為4。 具體的使用方法為,其中n稱為對(duì)齊系數(shù),取值必須是2的冪次方,即1、2、4、8、16等。

1. #pragma pack(show)     以警告信息的形式顯示當(dāng)前字節(jié)對(duì)齊的值.
2. #pragma pack(n)        將當(dāng)前字節(jié)對(duì)齊值設(shè)為 n .
3. #pragma pack()         將當(dāng)前字節(jié)對(duì)齊值設(shè)為默認(rèn)值(通常是8) .
4. #pragma pack(push)     將當(dāng)前字節(jié)對(duì)齊值壓入編譯棧棧頂.
5. #pragma pack(pop)      將編譯棧棧頂?shù)淖止?jié)對(duì)齊值彈出并設(shè)為當(dāng)前值.
6. #pragma pack(push, n)  先將當(dāng)前字節(jié)對(duì)齊值壓入編譯棧棧頂, 然后再將 n 設(shè)為當(dāng)前值.
7. #pragma pack(pop, n)   將編譯棧棧頂?shù)淖止?jié)對(duì)齊值彈出, 然后丟棄, 再將 n 設(shè)為當(dāng)前值.
8. #pragma pack(push, identifier)        將當(dāng)前字節(jié)對(duì)齊值壓入編譯棧棧頂, 然后將棧中保存該值的位置標(biāo)識(shí)為 identifier .
10. #pragma pack(pop, identifier)        將編譯棧棧中標(biāo)識(shí)為 identifier 位置的值彈出, 并將其設(shè)為當(dāng)前值. 注意, 如果棧中所標(biāo)識(shí)的位置之上還有值, 那會(huì)先被彈出并丟棄.
11. #pragma pack(push, identifier, n)    將當(dāng)前字節(jié)對(duì)齊值壓入編譯棧棧頂, 然后將棧中保存該值的位置標(biāo)識(shí)為 identifier, 再將 n 設(shè)為當(dāng)前值.
12. #pragma pack(pop, identifier, n)     將編譯棧棧中標(biāo)識(shí)為 identifier 位置的值彈出, 然后丟棄, 再將 n 設(shè)為當(dāng)前值. 注意, 如果棧中所標(biāo)識(shí)的位置之上還有值, 那會(huì)先被彈出并丟棄.
//注意: 如果在棧中沒有找到 pop 中的標(biāo)識(shí)符, 則編譯器忽略該指令, 而且不會(huì)彈出任何值.

通常成對(duì)使用:

#pragma pack (n)          //作用:編譯器將按照n個(gè)字節(jié)對(duì)齊。
#pragma pack ()           //作用:取消自定義字節(jié)對(duì)齊方式。


#pragma  pack (push,1)    //作用:是指把原來對(duì)齊方式設(shè)置壓棧,并設(shè)新的對(duì)齊方式設(shè)置為一個(gè)字節(jié)對(duì)齊
#pragma pack(pop)         //作用:恢復(fù)對(duì)齊狀態(tài)
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19899

    瀏覽量

    235438
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4381

    瀏覽量

    64947
  • 命令
    +關(guān)注

    關(guān)注

    5

    文章

    738

    瀏覽量

    22898
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2119

    瀏覽量

    75363
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1662

    瀏覽量

    50247
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    C語言常用的預(yù)處理命令

    1.基礎(chǔ)知識(shí)(1)C語言常用的預(yù)處理命令——typedef具體可見C語言基礎(chǔ)語法知識(shí)。(2)延時(shí)函數(shù)(知識(shí)粗略估計(jì)延時(shí)時(shí)間,若要精確延時(shí),需要用到后續(xù)的定時(shí)器)void delay(u
    發(fā)表于 07-14 07:10

    c語言預(yù)處理命令以什么開頭

    c語言預(yù)處理命令以什么開頭,目前我并沒有windows軟件編寫經(jīng)驗(yàn),對(duì)C語言的應(yīng)用也僅限于各種單片機(jī)的編程,所以對(duì)預(yù)處理的理解也只限于單片機(jī)
    發(fā)表于 07-20 07:00

    C語言預(yù)處理命令有哪些?

    不止。先看幾個(gè)個(gè)常識(shí)性問題: A) 預(yù)處理C 語言的一部分嗎? B) 包含“#”號(hào)的都是預(yù)處理嗎? C) 預(yù)處理指令后面都不需要加“;”號(hào)
    發(fā)表于 06-25 06:15

    Tcl/Tk命令C/C++的集成研究

    針對(duì) Tcl/Tk 腳本中需要調(diào)用C/C++函數(shù)的問題,簡要說明了Tcl/Tk 命令的運(yùn)行機(jī)理,給出了一個(gè)使用Tcl/Tk 命令來調(diào)用C/
    發(fā)表于 08-26 09:47 ?36次下載

    預(yù)處理器的工作原理作用

    預(yù)處理器的工作原理作用,希望對(duì)學(xué)者們有幫助。
    發(fā)表于 10-29 11:40 ?0次下載

    基于51單片機(jī)--C語言之預(yù)處理總結(jié)

    編譯預(yù)處理器是C語言編譯器的一個(gè)重要組成部分。很好的利用C語言的預(yù)處理命令可以增強(qiáng)代碼的可讀性,靈活性,和易于修改等特點(diǎn),便于程序的結(jié)構(gòu)化。
    發(fā)表于 08-17 10:48 ?1167次閱讀

    C語言常用的預(yù)處理命令和循環(huán)左移右移函數(shù)的詳細(xì)資料概述

    本文檔的主要內(nèi)容詳細(xì)介紹的是C語言常用的預(yù)處理命令和循環(huán)左移右移函數(shù)的詳細(xì)資料概述。
    發(fā)表于 10-22 08:00 ?71次下載

    C語言程序設(shè)計(jì)教程之預(yù)處理命令的詳細(xì)資料說明

    預(yù)處理命令的主要內(nèi)容:三種預(yù)處理命令,宏定義,文件包含,條件編譯
    發(fā)表于 02-26 14:43 ?13次下載
    <b class='flag-5'>C</b>語言程序設(shè)計(jì)教程之<b class='flag-5'>預(yù)處理</b><b class='flag-5'>命令</b>的詳細(xì)資料說明

    C++的const多文件編譯預(yù)處理的資料說明

    本文檔的主要內(nèi)容詳細(xì)介紹的是C++的const多文件編譯預(yù)處理的資料說明包括了:1、const型常量,2、常對(duì)象,3、常成員函數(shù),4、常數(shù)據(jù)成員,5、常引用,6、多文件,7、編譯預(yù)處,8、多文件結(jié)構(gòu)中使用編譯預(yù)處理的問題
    發(fā)表于 04-03 08:00 ?0次下載
    <b class='flag-5'>C++</b>的const多文件編譯<b class='flag-5'>預(yù)處理</b>的資料說明

    8051單片機(jī)的預(yù)處理命令的詳細(xì)資料說明

    在編寫程序時(shí),經(jīng)常會(huì)使用以“#”開頭的預(yù)處理命令。在對(duì)程序進(jìn)行編譯時(shí),會(huì)有專門的預(yù)處理程序來對(duì)這些命令進(jìn)行處理。
    發(fā)表于 06-11 17:47 ?0次下載
    8051單片機(jī)的<b class='flag-5'>預(yù)處理</b><b class='flag-5'>命令</b>的詳細(xì)資料說明

    C51的預(yù)處理命令和用戶配置文件詳細(xì)資料說明

    用戶編寫的C51程序代碼只能控制程序的執(zhí)行流程,若要對(duì)編譯程序進(jìn)行操作,就要用到預(yù)處理命令。在編譯環(huán)境對(duì)源程序進(jìn)行編譯前,先對(duì)程序中的預(yù)處理命令
    發(fā)表于 03-19 14:52 ?6次下載
    <b class='flag-5'>C</b>51的<b class='flag-5'>預(yù)處理</b><b class='flag-5'>命令</b>和用戶配置文件詳細(xì)資料說明

    C語言預(yù)處理命令分類工作原理詳細(xì)說明

    器,故在閱讀或開發(fā) C/C++ 程序過程中,可能會(huì)接觸大量的預(yù)處理指令。 1、預(yù)處理指令及分類 C
    發(fā)表于 11-25 10:34 ?18次下載
    <b class='flag-5'>C</b>語言<b class='flag-5'>預(yù)處理</b><b class='flag-5'>命令</b>的<b class='flag-5'>分類</b>和<b class='flag-5'>工作原理</b>詳細(xì)說明

    C語言預(yù)處理指令及分類

    C/C++ 程序中的源代碼中包含以 # 開頭的各種編譯指令,這些指令稱為預(yù)處理指令。預(yù)處理指令不屬于 C/
    的頭像 發(fā)表于 11-29 10:14 ?2545次閱讀

    C語言預(yù)處理命令是什么

    我們?cè)趯?b class='flag-5'>C語言程序時(shí)經(jīng)常使用庫函數(shù)之前,應(yīng)該用`#include`引入對(duì)應(yīng)的頭文件。這種以`#`號(hào)開頭的命令稱為預(yù)處理命令。
    的頭像 發(fā)表于 02-17 13:59 ?3387次閱讀
    <b class='flag-5'>C</b>語言<b class='flag-5'>預(yù)處理</b><b class='flag-5'>命令</b>是什么

    C預(yù)處理器及其工作原理

    C預(yù)處理器(C Pre-Processor)也常簡寫為 CPP,是一個(gè)與 C 編譯器獨(dú)立的小程序,預(yù)編譯器并不理解 C 語言語法,它僅是在程
    的頭像 發(fā)表于 03-12 14:14 ?1090次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>預(yù)處理</b>器及其<b class='flag-5'>工作原理</b>