C語言程序的編譯與預(yù)處理基礎(chǔ)定義講解
程序的翻譯環(huán)境和執(zhí)行環(huán)境
在ANSIC的任何一種實(shí)現(xiàn)中,存在兩個(gè)不同的環(huán)境:翻譯環(huán)境和執(zhí)行環(huán)境
翻譯環(huán)境:源代碼被轉(zhuǎn)換為可執(zhí)行的機(jī)器指令。
執(zhí)行環(huán)境:實(shí)際執(zhí)行代碼。
1.翻譯環(huán)境

- 組成一個(gè)程序的每個(gè)源文件通過編譯分別轉(zhuǎn)換成目標(biāo)文件(object code)。
- 每個(gè)目標(biāo)文件由鏈接器(linker)捆綁在一起,形成一個(gè)單一而完整的可執(zhí)行程序。
- 鏈接器同時(shí)也會(huì)引入標(biāo)準(zhǔn)C函數(shù)庫中任何被該程序所用到的函數(shù),而且它可以搜索程序員個(gè)人的程序庫,將齊需要的函數(shù)也鏈接到程序中。

2.運(yùn)行環(huán)境
程序的執(zhí)行環(huán)境:
1.程序必須載入內(nèi)存中。在有操作系統(tǒng)的環(huán)境中:一般這個(gè)由操作系統(tǒng)完成。在獨(dú)立的環(huán)境中,程序的載入必須由手工安排,也可能是通過可執(zhí)行代碼置入只讀內(nèi)存來完成。
2.程序的執(zhí)行便開始。接著便調(diào)用main函數(shù)。
3.開始執(zhí)行程序代碼。這個(gè)時(shí)候程序?qū)⑹褂靡粋€(gè)運(yùn)行時(shí)堆棧(stack),存儲(chǔ)函數(shù)的局部變量和返回地址。程序同時(shí)也可以使用靜態(tài)(static)內(nèi)存,存儲(chǔ)于靜態(tài)內(nèi)存中的變量在程序的整個(gè)執(zhí)行過程中一種保留它們的值。
4.終止程序。正常終止main函數(shù),也有可能是意外終止。
預(yù)處理詳解
預(yù)定義符號(hào)


#define
#define 定義標(biāo)識(shí)符
語法:
#define name stuff
#define MAX 100
#define REG register //為register創(chuàng)建一個(gè)簡(jiǎn)短的名字
#define do_forever for(;;) //用符號(hào)來替換一種實(shí)現(xiàn)
#define PRINT printf("file:%s\tline:%d\tdate:%s\time:%s\n", \
__FILE__,__LINE__,__DATE__,__TIME__)
//如果定義的stuff過長(zhǎng),可以分成幾行來寫,除了最后一行外,每行的后面都加一個(gè)反斜杠(續(xù)行符)。
在define定義標(biāo)識(shí)符的時(shí)候,最后不要加(;)號(hào)。
#define定義宏
#define機(jī)制包括了一個(gè)規(guī)定,允許把參數(shù)替換到文本中,這種實(shí)現(xiàn)通常稱為宏(macro)或定義宏(define macro)。
宏的聲明方式:
#define name ( parament - list ) stuff 其中的parament - list 是一個(gè)由逗號(hào)隔開的符號(hào)表,它們可能出現(xiàn)在stuff中。
參數(shù)列表的左括號(hào)必須與name緊緊相鄰。若兩者之間存在空白,參數(shù)列表就會(huì)被解釋為stuff的一部分。
#define SQUARE( x ) x * x

#define替換規(guī)則
1.在調(diào)用宏時(shí),首先對(duì)參數(shù)進(jìn)行檢查,看看是否包含任何由#define定義的符號(hào)。如果是,它們將首先被替換。
2.替換文本隨后被插入到程序中原來文本的位置。對(duì)于宏,參數(shù)名被它們的值替換。
3.最后,再一次對(duì)結(jié)果文件進(jìn)行掃描,看看是否還包含任何由#define定義的符號(hào)。如果是,就重復(fù)上述的過程。
注意:
1.宏參數(shù)和#define定義中可以出現(xiàn)其它#define定義的變量。但是對(duì)于宏,不能出現(xiàn)遞歸。
2.當(dāng)預(yù)處理器搜索#define定義的符號(hào)的時(shí)候,字符串常量的內(nèi)容并不被搜索。
#和##
如何把參數(shù)插入到字符串中?

#include<stdio.h>
#define PRINT(n) printf("the value of "#n" is %d\n",n)
int main()
{
int a = 7;
PRINT(a);
int b = 5;
PRINT(b);
return 0;
}##的作用:

帶副作用的宏參數(shù)
當(dāng)宏參數(shù)在宏的定義中出現(xiàn)超過一次的時(shí)候,如果參數(shù)帶有副作用,那么在使用這個(gè)宏的時(shí)候就可能會(huì)出現(xiàn)危險(xiǎn),導(dǎo)致不可預(yù)知的后果。副作用就是表達(dá)式求值的時(shí)候出現(xiàn)的永久性效果。
x+1;//不帶有副作用 x++;//帶有副作用
舉一個(gè)例子:

宏和函數(shù)對(duì)比
宏通常被應(yīng)用于執(zhí)行簡(jiǎn)單的運(yùn)算。例如在找出兩個(gè)數(shù)中的較大一個(gè)。
#define MAX(a, b) ((a)>(b)?(a):(b))
為什么不用函數(shù)來完成這個(gè)任務(wù)呢?有其下原因:
1.用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實(shí)際執(zhí)行這個(gè)小型計(jì)算工作所需要的時(shí)間更多。所以宏比函數(shù)在程序的規(guī)模和速度方面更勝一籌。
2.函數(shù)的參數(shù)必須聲明為特定的類型。所以函數(shù)只能在類型合適的表達(dá)式上使用。而這個(gè)宏可以適用于整形、長(zhǎng)整型、浮點(diǎn)型等類型。宏是類型無關(guān)的。

宏和函數(shù)的對(duì)比:

命名約定
一般來講函數(shù)和宏的使用語法非常相似。所以語法本身沒有辦法幫我們區(qū)分二者。
所以一般是:把宏名全部大寫,函數(shù)名不要全部大寫。
#undef
這條指令用于移除一個(gè)宏定義。
#undef NAME //如果現(xiàn)存的一個(gè)名字需要被重定義,那么它的舊名字首先要被移除
例如:

命令行定義
許多C的編譯器提供了一種功能,允許程序在命令行中定義符號(hào)。用于啟動(dòng)編譯過程。
例如:當(dāng)我們根據(jù)同一個(gè)源文件要編譯出不同的一個(gè)程序的不同版本的時(shí)候,這個(gè)特性就比較有用。(若某個(gè)程序中聲明了一個(gè)某長(zhǎng)度的數(shù)組,若機(jī)器內(nèi)存有限,我們需要一個(gè)很小的數(shù)組,若機(jī)器內(nèi)存大一些,我們就需要一個(gè)大一點(diǎn)的數(shù)組)。

條件編譯
在編譯一個(gè)程序的時(shí)候如果要將一條語句或者一組語句編譯或者放棄是很方便的。可以用條件編譯指令。
常見的條件編譯指令:

文件包含
#include指令可以使另外一個(gè)文件被編譯。
這種替換的方式:預(yù)處理先刪除這條指令,并用包含文件的內(nèi)容替換。這樣一個(gè)源文件被包含幾次,那就實(shí)際被編譯幾次。
頭文件被包含的方式:

通常一個(gè)大型的項(xiàng)目會(huì)調(diào)用多個(gè)程序合并,那么如何避免頭文件的重復(fù)包含而提高效率呢?
常見的有一下兩種解決方法:
1.每個(gè)頭文件的開頭寫:
#ifndef __TEST_H__ #define __TEST_H__ //頭文件的內(nèi)容 #endif
2.定義頭文件之前包含這一句話:
#pragma once
到此這篇關(guān)于C語言程序的編譯與預(yù)處理基礎(chǔ)定義講解的文章就介紹到這了,更多相關(guān)C語言編譯與預(yù)處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)一鍵關(guān)閉桌面的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)一鍵關(guān)閉桌面的功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-07-07
C++程序自動(dòng)重啟的實(shí)現(xiàn)代碼
自動(dòng)重啟原理很簡(jiǎn)單,用一個(gè)進(jìn)程監(jiān)控另一個(gè)進(jìn)程,掛了就再啟動(dòng)一個(gè),細(xì)節(jié)也不算多,主要是正確判斷進(jìn)程狀態(tài)和啟動(dòng)方式,本文就給大家講講C++程序自動(dòng)重啟的實(shí)現(xiàn)方法,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-04-04

