国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C/C++ - C語言編程之預(yù)處理過程與define及條件編譯

C語言編程之預(yù)處理過程與define及條件編譯

2022-01-07 14:34Booksort C/C++

這篇文章主要為大家介紹了C語言編程之預(yù)處理過程與define及條件編譯,文中通過圖文及示例代碼方式作了詳細的解釋,有需要的朋友可以借鑒參考下

這張圖描述了從源文件到可執(zhí)行文件的整體步驟:

C語言編程之預(yù)處理過程與define及條件編譯

這張圖展示了大體上步驟。

C語言編程之預(yù)處理過程與define及條件編譯

從代碼到運行環(huán)境,編譯器提供了翻譯環(huán)境。在一個程序中,會存在多個文件 ,而每個源文件都會單獨經(jīng)過編譯器處理。

C語言編程之預(yù)處理過程與define及條件編譯

預(yù)編譯:
1,會將#include等頭文件所包含的內(nèi)容,庫函數(shù)全部拷貝過來
2,代碼中注釋的刪除
3,由#define所定義的符號全部替換進代碼中
對預(yù)處理指令的操作

編譯:把C代碼翻譯成匯編代碼
1,語法分析(判斷是否存在語言的語法錯誤而造成無法編譯)
2,詞法分析
3,語義分析(分析每句代碼的意思)
4,符號匯總(會將整個程序中的全局符號進行匯總)

匯編
1,形成符號表

C語言編程之預(yù)處理過程與define及條件編譯

一個程序,兩個文件test.c與add.c,在test.c中,有

extern int add(int x,int y);//聲明對該函數(shù)引用,在其他文件中找該函數(shù)。

在匯編時,各個文件都會形參函數(shù)符號表,但extern并不會形成地址標記,只是一個0x00。

鏈接:合并段表
符號表的合并與重定位檢查各個函數(shù)及其定義聲明

C語言編程之預(yù)處理過程與define及條件編譯

 

名示常量#define

define的預(yù)處理指令

#define MACRO substitution
預(yù)處理指令 宏 替換體

宏只是起到替換作用,在替換過程中不產(chǎn)生任何運算
舉個例子

#define SUM 2+2
int num = SUM * SUM;

不了解的人可能會認為是
num=44;
但,實際是替換作用
num=2+22+2;
這就是宏只起到替換作用的意思。

再來介紹一個原理性概念

記號
從技術(shù)角度來看,可以把宏的替換體看作是記號型字符串。而不是字符型字符串。在C預(yù)處理器記號是宏定義的替換體的中單獨的“詞”,用空白把詞分開。例如:

#define FOUR 2*2
#define FOURS 2 * 2

這兩個對于預(yù)處理器要看預(yù)處理器把這個替換體看成什么。如果是字符型字符串,這空格也會是字符串的一部分。但如果是記號型字符串,空格就會被認為是分隔符,就和2*2是一個意思。總之要看編譯器的規(guī)則。
總結(jié)一下

如果編譯器理解替換體是字符型字符串,那么空格就會被認為是字符串的一部分
2 * 2就和2*2不是一個意思。
如果編譯器理解為記號型字符串,那么空格就會被認為只是分隔符,并不影響。空格不算替換體的一部分
2 * 2和2乘2則是一個意思。

 

重定義常量

假設(shè)把MAX設(shè)為30,在文件中又把它重新定義為10.這個過程叫重定義常量但不同的標準有不同的規(guī)則。有一些允許重定義,但是會報警。ANSI標準則采用,只有新舊定義完全相同才允許重定義。
完全相同意味著替換體中必須記號完全相同,順序也必須相同

#define MAX 2 * 3
#define MAX 2 * 3

這才允許

#define MAX 2 * 3
#define MAX 2*3

這不符合那個標準。(雖然我不知道這個標準的重定義有什么用,我比較菜)
注:根據(jù)一個大佬的建議,這類代碼非常致命,非常不好,最好不使用。

 

在#define中使用參數(shù)

在#define中也可以創(chuàng)建外形和作用與函數(shù)類似的類函數(shù)宏
帶有函數(shù)的宏可以達到部分函數(shù)的作用。

#define	SQUARE(X) X*X
mul=SQUARE(2);

與函數(shù)調(diào)用有些相似。
同時最好使用足夠多的括號去確保運算和結(jié)合性的正確。

mul=SQUARE(x++)

則會造成運算不符合要求。

用宏參數(shù)創(chuàng)建字符串:#運算符

#define PSQRA(X) printf("X is %d\n",((X)*(X));
#define PSQRB(X) printf("#X" is %d\n",((X)*(X));

這兩個是可以打印出不同的效果
#作為一個預(yù)處理運算符,可以把記號轉(zhuǎn)換成字符串,如果X是一個宏形參,那么#X就是“X”的字符串的形參名。

這叫字符串化

int y=50;
PSQRA(y)
X is 2500
PSQRB(Y)
y is 2500
PSQRA(2+4)
X is 36
PSQRB(2+4)
2+4 is 36

這就是區(qū)別。

 

預(yù)處理器粘合劑:##運算符

#運算符可以作用于宏的替換體
而##運算符也可以作用。

#define NUMBER(n) X##n
NUMBER(4)可展開為x4

例如

#include <stdio.h>
#define XNAME(N) x##N
#define PRINT(N) pritnf("x"#N"=%d\n",x##N);
int main(void)
{
	int XNAME(1) = 10;//x1=10
	int XNAME(2) = 20;//x2=10
	int x3 = 0;
	PRINT(1);//printf("x1=%d",x1);
	PRINT(2);//printf("x2=%d",x2);
	PRINT(3);//printf("x3=%d",x3);
}

C語言編程之預(yù)處理過程與define及條件編譯

 

變參宏:… 和_ _ VAG_ARGS_ _

一些函數(shù)可以接受數(shù)量可變的參數(shù)(就是沒有固定傳遞的參數(shù)的數(shù)量,如printf()和scanf())。而宏也可以擁有這樣的能力。

#define PR(...) printf(_ _VAG_ARGS_ _)
PR("HELLO WORLD");//printf("HELLO WORLD");
PR("x1=%d,x2=%d",10,20);//printf(""x1=%d,x2=%d",10,20);

相當于這樣的效果。
省略號只能代替最后的宏參數(shù)。不能在省略號加其他參數(shù)。

#define PR(x,...,y) #x #_ _VAG_ARGS_ _ #y

是不被允許的。

 

宏與函數(shù)

有相當一部分的宏可以起到和函數(shù)一樣的效果,但到底該怎么選呢?
宏和函數(shù)可以達到同樣效果。宏比函數(shù)要簡單一些,同時,在編譯器的消耗時間也要遠小于函數(shù)。但是稍有不慎就會產(chǎn)生一些副作用,導(dǎo)致結(jié)果不可預(yù)測。
宏與函數(shù)的比較實際上就是關(guān)于時間與空間的比較。

宏在預(yù)編譯的時候會生成內(nèi)聯(lián)代碼,也就是會在程序中替換生成語句。如果調(diào)用20次,則會在程序中插入20行代碼。

但如果調(diào)用函數(shù)20次,函數(shù)也只有一份副本,節(jié)省了相當一部分空間。但執(zhí)行函數(shù)時,要調(diào)用,再執(zhí)行,再返回,遠比宏插入內(nèi)聯(lián)語句消耗的時間要多。

宏較函數(shù)也存在缺陷

  • 當宏較大時會增加代碼長度。
  • 宏是無法調(diào)試(在預(yù)編譯的時候就已完成替換),可能會出現(xiàn)問題。
  • 宏由于不要求類型,會造成不嚴謹(這也是對于函數(shù)的一個好處,函數(shù)傳參會要求參數(shù)類型,而宏只會將參數(shù)當作字符串處理,只要是int或float類型都可以)
  • 宏可能會帶來運算符優(yōu)先級的問題,使運算不可預(yù)測。

自己按照情況去使用。如果使用宏容易出現(xiàn)副作用,那還是調(diào)用函數(shù)吧。

但要記住以下幾

1,記住宏名中不允許有空格,但在替換字符串中可以有空格。ANSI C允許在參數(shù)列表中使用空格。

2,用括號把宏的參數(shù)和替換體括起來,正確展開,防止出現(xiàn)副作用。

3,一般用大寫字母表示宏常量,一般不全大寫表示宏函數(shù)

4,如果用宏來加快函數(shù)的運行速度,要先確定宏和函數(shù)之間是否有差距。且,如果只使用一次那對速度加快影響不大。最好在多重嵌套中使用。

 

預(yù)處理指令

當編譯器碰上#include 指令時,會查看后面文件名并把內(nèi)容添加到當前文件中。

#include <stdio.h>//查找系統(tǒng)目錄文件
#include "mtfile.h"//查找當前工作目錄
#include "/usr/biff/file.h"//查找/usr/biff/目錄

不同的系統(tǒng)有不同的規(guī)則,但<>與“”的規(guī)則是不變的。

通過頭文件的引用,我們才能使用各種函數(shù)。頭文件中有各種函數(shù)的聲明。再通過庫文件去調(diào)用函數(shù)的原型。

 

#undef指令

可以通過該指令去向之前#define定義的宏

#include <stdio.h>
#define MAX 10
#undef MAX
int main(void)
{
	printf("%d", MAX);
}

C語言編程之預(yù)處理過程與define及條件編譯

直接報錯
#undef可以取消,某個宏的定義,可以用用來防止某個宏被重復(fù)定義,造成錯誤。

 

從C預(yù)處理器的角度看已定義

預(yù)處理器在處理標識符時遵循相同規(guī)則。當預(yù)處理器發(fā)現(xiàn)一個標識符時,會將其當作已定義或未定義。而這里的已定義是由預(yù)處理器決定。如果該標識符是由define定義的且沒有undef取消,那就是已定義。如果是定義的某個全局變量,那就是未定義(對預(yù)處理器而言)。

#define定義的宏的作用域從文件開頭開始,延申至文件結(jié)尾或者遇到#undef取消定義,如果跨文件使用,那使用的位置要在#include引用的文件后。

 

條件編譯

就跟條件判斷語句有著類似的意思。

#ifdef , #else , #endif

舉個例子

#include <stdio.h>
#define MAX 10
#undef MAX
#ifdef MAX
	#include <string.h>
	#define MIN 10
#endif // 
int main(void)
{
	printf("%d", MIN);
}

C語言編程之預(yù)處理過程與define及條件編譯

結(jié)果就是這個。
但屏蔽#undef

#include <stdio.h>
#define MAX 10
//#undef MAX
#ifdef MAX
	#include <string.h>
	#define MIN 10
#endif // 
int main(void)
{
	printf("%d", MIN);
}

C語言編程之預(yù)處理過程與define及條件編譯

可以運行。
條件編譯指令與條件判斷語句類似。
只不過,條件判斷語句是判讀是否執(zhí)行,
二條件編譯指令是判斷是否進行預(yù)編譯。
#endif用來結(jié)束該指令的范圍
再引入一個指令

#ifndef DEBUG

如果DEBUG未定義就執(zhí)行編譯,如果已定義就不執(zhí)行。

還有這幾個指令,非常接近條件判斷語句

#if ,#elif ,#else

#if和#elif與if和else if類似。但它們的后面接整形常量表達式。
0為假,非0為真
都是判斷是否進行預(yù)編譯

可以通過條件編譯指令去防止某些文件被多次調(diào)用導(dǎo)致問題出現(xiàn)

#ifndef _FILE_H
#define _FILE_H
文件內(nèi)容
。
。
#endif

或者直接使用

#pragma once
//可以保證文件只是使用一次

 

offsetof函數(shù)

size_t offsetof( structName, memberName );

用于測算結(jié)構(gòu)體成員相對于起始位置的偏移量

實現(xiàn)

#define OFFSETOF(structName,memberName) (int)&(((struct structName*)0)->memberName)

從0地址處,開始向成員訪問再取地址在強轉(zhuǎn)成整形。

以上就是C語言編程之預(yù)處理過程與define及條件編譯的詳細內(nèi)容,更多關(guān)于C語言預(yù)處理的資料請關(guān)注服務(wù)器之家其它相關(guān)文章!

原文鏈接:https://blog.csdn.net/weixin_52199109/article/details/115048443

延伸 · 閱讀

精彩推薦
  • C/C++深入理解goto語句的替代實現(xiàn)方式分析

    深入理解goto語句的替代實現(xiàn)方式分析

    本篇文章是對goto語句的替代實現(xiàn)方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網(wǎng)7342020-12-03
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數(shù)使用

    詳解c語言中的 strcpy和strncpy字符串函數(shù)使用

    strcpy 和strcnpy函數(shù)是字符串復(fù)制函數(shù)。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數(shù)使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C語言實現(xiàn)電腦關(guān)機程序

    C語言實現(xiàn)電腦關(guān)機程序

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)電腦關(guān)機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C/C++經(jīng)典實例之模擬計算器示例代碼

    C/C++經(jīng)典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關(guān)于C/C++經(jīng)典實例之模擬計算器的相關(guān)資料,文中通過示...

    jia150610152021-06-07
  • C/C++學(xué)習(xí)C++編程的必備軟件

    學(xué)習(xí)C++編程的必備軟件

    本文給大家分享的是作者在學(xué)習(xí)使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++c++ 單線程實現(xiàn)同時監(jiān)聽多個端口

    c++ 單線程實現(xiàn)同時監(jiān)聽多個端口

    這篇文章主要介紹了c++ 單線程實現(xiàn)同時監(jiān)聽多個端口的方法,幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內(nèi)存中的數(shù)據(jù)都是暫時的,當程序結(jié)束時,它們都將丟失,為了永久性的保存大量的數(shù)據(jù),C語言提供了對文件的操作,這篇文章主要給大家介紹了關(guān)于C語言中文件...

    針眼_6702022-01-24
主站蜘蛛池模板: 亚洲午夜av | 久久久人成影片一区二区三区 | 中文字幕在线免费看 | 寡妇性视频免费高清播放器 | 观看av| 一级免费毛片 | 99久久视频 | 色猫猫国产区一区二在线视频 | 日韩城人网站 | 在线观看一区二区视频 | 欧美日韩一 | 成人免费观看cn | 亚洲综合色网 | 欧美综合激情 | 懂色av中文字幕一区二区三区 | 91精选| 成人av福利 | 播放欧美一级片 | h视频免费观看 | 成人精品福利视频 | 亚洲成人在线观看视频 | 三级成人在线 | 亚洲一区二区三区高清 | 免费成人av在线 | 黄色小视频在线免费观看 | 中文字幕一区二区三区乱码图片 | 狠狠的日 | 99久久久久久 | 中文字幕在线电影观看 | 亚洲欧美日韩精品久久亚洲区 | 久久久久99 | 精品麻豆剧传媒av国产九九九 | 女人色网| 国产视频一二区 | 免费a级毛片在线观看 | 欧美午夜一区二区三区免费大片 | 欧美a在线| 日韩中文字幕 | 午夜精品久久久久久久白皮肤 | 成人在线网址 | 韩日一区二区三区 |