欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言進(jìn)階教程之預(yù)處理

 更新時間:2023年02月10日 10:09:14   作者:sukuni  
C語言提供了多種預(yù)處理功能,如宏定義、文件包含、條件編譯等,下面這篇文章主要給大家介紹了關(guān)于C語言進(jìn)階教程之預(yù)處理的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

一.代碼運(yùn)行是的兩種環(huán)境

1.翻譯環(huán)境,在這個環(huán)境中源代碼被轉(zhuǎn)換為可執(zhí)行的機(jī)器指令。
2.執(zhí)行環(huán)境,它用于實(shí)際執(zhí)行代碼

下面主要講解翻譯環(huán)境。

二.翻譯環(huán)境

從.c 文件到 .exe 文件需要經(jīng)過編譯器的翻譯,而翻譯又分為 編譯和鏈接兩個部分

編譯又分為三個部分:

1.預(yù)編譯:又叫預(yù)處理,在這個部分主要完成頭文件的包含,#define的替換,注釋的刪除;

2.編譯:主要完成語法分析,詞法分析,詞義分析,符號匯總(符號包括全局性的變量和函數(shù)),生成匯編代碼;

3.匯編:生成二進(jìn)制指令,形成符號表(符號表是由符號和其地址組成的);

鏈接:合并段表,合并符號表(在這個階段會發(fā)現(xiàn)未定義的函數(shù))。

見下圖:

三.預(yù)定義符號

__FILE__    //進(jìn)行編譯的源文件
__LINE__   //文件當(dāng)前的行號
__DATE__   //文件被編譯的日期
__TIME__   //文件被編譯的時間
__STDC__   //如果編譯器遵循ANSI C,其值為1,否則未定義

四.#define

1.define  定義宏

宏的申明方式:

#define name( parament-list ) stuff
其中的 parament-list 是一個由逗號隔開的符號表,它們可能出現(xiàn)在stuff中。

注意 name 需與后面的括號緊密相連,不可以有空格,如果有任何空白存在,參數(shù)列表就會被解釋為stuff的一部分。

注意當(dāng)我們定義宏的時候,不要吝嗇括號!

來看下面一個例子:

#define MOD(x,y) x*y
 
int main()
{
	int m = MOD(2+3,2);
	printf("%d\n", m);
	return 0;
}

對初學(xué)者來說,這段代碼的答案很容易被認(rèn)為式10,但事實(shí)并非如此,因?yàn)楹晔窃陬A(yù)處理階段先替換掉,然后在進(jìn)行計(jì)算,所以在沒有括號的情況下,替換后是這樣的:2+3*2=8;所以若是想要得到10這個結(jié)果,就要加上括號,即:

#define MOD(x,y) ((x)*(y))

2.帶有副作用的宏參數(shù)

我們知像是前置++ ,后置++這種的運(yùn)算符是會改變操作數(shù)的值屬性的,那它如果應(yīng)用到#define 定義的宏中會是怎么樣呢?

我們來看下面這個例子:

#define MAX(x,y) ((x)>(y)?(x):(y))
 
int main()
{
	int a = 4;
	int b = 6;
	int m = MAX(a++, b++);
	printf("m=%d\n", m);
	printf("a=%d b=%d\n", a, b);
	return 0;
}

最后的答案會是多少呢?

首先完成宏參數(shù)的替換:((a++)>(b++)?(a++):(b++))

后置++是先使用后++,因?yàn)?<6,所以執(zhí)行后面的 b++,經(jīng)過前面的++,此時a=5,b=7,所以先把7賦給m,然后b++,得到b=8;

即m=7  a=5  b=8

總結(jié): 

1.#define 定義的符號需要先原封不動的替換掉,所以建議在#define 后面不加 ' ; ' ;

2.#define 定義的宏不要吝嗇括號,以免出現(xiàn)出乎意料的結(jié)果;

3.避免使用帶有副作用的運(yùn)算符。

五.#define定義宏 與函數(shù)對比

六.預(yù)處理指令

所有的預(yù)處理指令都是以井號(#)開頭。它必須是第一個非空字符,為了增強(qiáng)可讀性,預(yù)處理指令應(yīng)從第一列開始。下面列出了所有重要的預(yù)處理指令:

七.條件編譯

可以實(shí)現(xiàn)將一條語句(一組語句)編譯或者放棄。

常見的條件編譯指令:

1.
#if 常量表達(dá)式
//...
#endif
//常量表達(dá)式由預(yù)處理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif

 例:

int main()
{
#if 1    //如果這個常量表達(dá)式為真,則執(zhí)行后面的語句,反之則不執(zhí)行
	printf("haha\n");
#endif
	return 0;
}

運(yùn)行結(jié)果:

2.多個分支的條件編譯
#if 常量表達(dá)式
//...
#elif 常量表達(dá)式 (注意這里是 elif ,而不是else if )
//...
#else
//...
#endif 

例:

#define M 10
 
int main()
{
#if M==5
	printf("mafumafu\n");
#elif M==10
	printf("Eve\n");
#elif M==7
	printf("Sou\n");
#elif M==2
	printf("amatsuki\n");
#else 
	printf("soraru");
#endif
	return 0;
}

運(yùn)行結(jié)果:

3.嵌套指令 

        #if defined(OS_UNIX)    //如果定義了,則往下執(zhí)行
                #ifdef OPTION1
                        unix_version_option1();
                #endif
                #ifdef OPTION2
                        unix_version_option2();
                #endif
                #elif defined(OS_MSDOS)
                #ifdef OPTION2
                        msdos_version_option2();
                #endif
        #endif

八.頭文件包含的方式

1.  雙引號式 #include "test.h"  :先在源文件所在目錄下查找,如果該頭文件未找到,編譯器                                                     就像查找?guī)旌瘮?shù)頭文件一樣在標(biāo)準(zhǔn)位置查找頭文件。
                                                 如果找不到就提示編譯錯誤。

2.尖括號式 #include <stdio.h>: 查找頭文件直接去標(biāo)準(zhǔn)路徑下去查找,如果找不到就提示編                                                     譯錯誤。

所以說庫里的頭文件也可以用 雙引號 包含 ,但并不建議這樣做,因?yàn)殡p引號包含沒有尖括號包含的查找的快。

嵌套文件包含

 comm.h和comm.c是公共模塊。
test1.h和test1.c使用了公共模塊。
test2.h和test2.c使用了公共模塊。
test.h和test.c使用了test1模塊和test2模塊。
這樣最終程序中就會出現(xiàn)兩份comm.h的內(nèi)容。這樣就造成了文件內(nèi)容的重復(fù)。

如何防止這種問題出現(xiàn)?

有兩種解決方式:

1.利用條件編譯指令

#ifndef __TEST_H__   //如果沒有定義  TEST_H__  則執(zhí)行下一句代碼  定義 __TEST_H__
#define __TEST_H__
#endif

2.利用預(yù)處理指令  #pragma   once

《高質(zhì)量C/C++編程指南》中的兩個問題

1. 頭文件中的 ifndef/define/endif是干什么用的?

   防止頭文件的重復(fù)引用。
2. #include <filename.h> 和 #include "filename.h"有什么區(qū)別?

   文件的查找策略不同。

總結(jié)

到此這篇關(guān)于C語言進(jìn)階教程之預(yù)處理的文章就介紹到這了,更多相關(guān)C語言預(yù)處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于C++中覆蓋,重載,隱藏的一點(diǎn)重要說明

    基于C++中覆蓋,重載,隱藏的一點(diǎn)重要說明

    下面小編就為大家?guī)硪黄贑++中覆蓋,重載,隱藏的一點(diǎn)重要說明。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • OpenCV使用鼠標(biāo)響應(yīng)裁剪圖像

    OpenCV使用鼠標(biāo)響應(yīng)裁剪圖像

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)鼠標(biāo)響應(yīng)裁剪圖像,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C++利用伴隨陣法實(shí)現(xiàn)矩陣求逆

    C++利用伴隨陣法實(shí)現(xiàn)矩陣求逆

    這篇文章主要為大家詳細(xì)介紹了C++如何利用伴隨陣法實(shí)現(xiàn)矩陣求逆,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)和借鑒價(jià)值,需要的可以參考一下
    2023-02-02
  • C語言編寫學(xué)生成績管理系統(tǒng)

    C語言編寫學(xué)生成績管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言編寫學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 詳解C語言中的rename()函數(shù)和remove()函數(shù)的使用方法

    詳解C語言中的rename()函數(shù)和remove()函數(shù)的使用方法

    這篇文章主要介紹了詳解C語言中的rename()函數(shù)和remove()函數(shù)的使用方法,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • 解決C++中重定義的方法總結(jié)

    解決C++中重定義的方法總結(jié)

    本篇文章是對C++中重定義的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++實(shí)現(xiàn)教師管理系統(tǒng)

    C++實(shí)現(xiàn)教師管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)教師管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vscode中配置LeetCode插件的教程(愉快刷題)

    vscode中配置LeetCode插件的教程(愉快刷題)

    這篇文章主要介紹了vscode中配置LeetCode插件的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-03-03
  • C++設(shè)計(jì)模式之職責(zé)鏈模式

    C++設(shè)計(jì)模式之職責(zé)鏈模式

    這篇文章主要介紹了C++設(shè)計(jì)模式之職責(zé)鏈模式,本文講解了什么是職責(zé)鏈模式、什么場合下使用、代碼實(shí)例等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • C語言實(shí)現(xiàn)掃雷小游戲(適合初學(xué)者)

    C語言實(shí)現(xiàn)掃雷小游戲(適合初學(xué)者)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)掃雷小游戲,適合初學(xué)者練習(xí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03

最新評論