亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語(yǔ)言中程序環(huán)境和預(yù)處理的詳細(xì)圖文講解

 更新時(shí)間:2023年02月16日 09:37:26   作者:平凡的小蘇  
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中程序環(huán)境和預(yù)處理的相關(guān)資料,我們寫(xiě)的C語(yǔ)言代碼,從運(yùn)行,到在屏幕上生成結(jié)果,經(jīng)歷了比較復(fù)雜的過(guò)程,需要的朋友可以參考下

1. 程序的翻譯環(huán)境和執(zhí)行環(huán)境 

在 ANSI C 的任何一種實(shí)現(xiàn)中,存在兩個(gè)不同的環(huán)境。

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

2. 詳解編譯+鏈接 

2.1 翻譯環(huán)境

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

編譯分為三步驟(如下圖所示) 

2.2 編譯本身也分為幾個(gè)階段

1. 預(yù)處理: 選項(xiàng) gcc - E test.c - o test.i
    預(yù)處理完成之后就停下來(lái),預(yù)處理之后產(chǎn)生的結(jié)果都放在 test.i 文件中。
2. 編譯 :選項(xiàng) gcc - S test.c
    編譯完成之后就停下來(lái),結(jié)果保存在 test.s 中。
3. 匯編 : gcc - c test.c
    匯編完成之后就停下來(lái),結(jié)果保存在 test.o 中

2.3 運(yùn)行環(huán)境  

程序執(zhí)行的過(guò)程:

1. 程序必須載入內(nèi)存中。在有操作系統(tǒng)的環(huán)境中:一般這個(gè)由操作系統(tǒng)完成。在獨(dú)立的環(huán)境中,程序的載入必須由手工安排,也可能是通過(guò)可執(zhí)行代碼置入只讀內(nèi)存來(lái)完成。

2. 程序的執(zhí)行便開(kāi)始。接著便調(diào)用 main 函數(shù)。

3. 開(kāi)始執(zhí)行程序代碼。這個(gè)時(shí)候程序?qū)⑹褂靡粋€(gè)運(yùn)行時(shí)堆棧(stack),存儲(chǔ)函數(shù)的局部變量和返回地址。程序同時(shí)也可以使用靜態(tài)(static )內(nèi)存,存儲(chǔ)于靜態(tài)內(nèi)存中的變量在程序的整個(gè)執(zhí)行過(guò)程一直保留他們的值。

4. 終止程序。正常終止 main 函數(shù);也有可能是意外終止。

3. 預(yù)處理詳解

3.1 預(yù)定義符號(hào)

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

舉個(gè)栗子:這些預(yù)定義符號(hào)都是內(nèi)置的

#include<stdio.h>
int main()
{
	printf("file:%s line:%d\n", __FILE__, __LINE__);
	return 0;
}

這兩個(gè)預(yù)定義符號(hào)會(huì)在屏幕打印出源文件路徑,和該代碼在哪一行 

3.2 #define

3.2.1 #define 定義標(biāo)識(shí)符

提問(wèn): 在define定義標(biāo)識(shí)符的時(shí)候,要不要在最后加上 ; ? 比如:

#define MAX 1000;
#define MAX 1000

建議不要加上 ; ,這樣容易導(dǎo)致問(wèn)題。

比如下面的場(chǎng)景:

if(condition)
 max = MAX;
 else
 max = 0;

 這里會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤。

3.2.2 #define 定義宏 

#define 機(jī)制包括了一個(gè)規(guī)定,允許把參數(shù)替換到文本中,這種實(shí)現(xiàn)通常稱(chēng)為宏(macro)或定義

宏(define macro)。

下面是宏的申明方式:

#define name( parament - list ) stuff

其中的 parament - list 是一個(gè)由逗號(hào)隔開(kāi)的符號(hào)表,它們可能出現(xiàn)在 stuff 中。

注意:

參數(shù)列表的左括號(hào)必須與 name 緊鄰。

如果兩者之間有任何空白存在,參數(shù)列表就會(huì)被解釋為 stuff 的一部分。

如:

#define SQUARE( x ) x * x

這個(gè)宏接收一個(gè)參數(shù) x . 如果在上述聲明之后,你把SQUARE( 5 );

置于程序中,預(yù)處理器就會(huì)用下面這個(gè)表達(dá)式替換上面的表達(dá)式。

警告: 這個(gè)宏存在一個(gè)問(wèn)題: 觀察下面的代碼段:
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );
替換文本時(shí),參數(shù)x被替換成a + 1,所以這條語(yǔ)句實(shí)際上變成了:
printf ("%d\n",a + 1 * a + 1 );
這樣就比較清晰了,由替換產(chǎn)生的表達(dá)式并沒(méi)有按照預(yù)想的次序進(jìn)行求值。
在宏定義上加上兩個(gè)括號(hào),這個(gè)問(wèn)題便輕松的解決了

3.2.3 #define 替換規(guī)則

在程序中擴(kuò)展 #define 定義符號(hào)和宏時(shí),需要涉及幾個(gè)步驟。

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

3.2.4 #和##  

如何把參數(shù)插入到字符串中?

首先我們看看這樣的代碼:

char* p = "hello ""bit\n";
printf("hello"" bit\n");
printf("%s", p);

這里輸出的是不是

hello bit ?

答案是確定的:是。

我們發(fā)現(xiàn)字符串是有自動(dòng)連接的特點(diǎn)的。

1.使用 # , 把一個(gè)宏參數(shù)變成對(duì)應(yīng)的字符串

int i = 10;
#define PRINT(FORMAT, VALUE)\
 printf("the value of " #VALUE "is "FORMAT "\n", VALUE);
...
PRINT("%d", i+3);//產(chǎn)生了什么效果

最終的輸出的結(jié)果應(yīng)該是:

the value of i + 3 is 13

## 的作用 

##可以把位于它兩邊的符號(hào)合成一個(gè)符號(hào)。 它允許宏定義從分離的文本片段創(chuàng)建標(biāo)識(shí)符。 
#define ADD_TO_SUM(num, value) \ sum##num += value;...ADD_TO_SUM(5, 10);//作用是:給sum5增加10.
注: 這樣的連接必須產(chǎn)生一個(gè)合法的標(biāo)識(shí)符。否則其結(jié)果就是未定義的。

3.2.5 帶副作用的宏參數(shù)  

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

x + 1 ; // 不帶副作用
x ++ ; // 帶有副作用

MAX宏可以證明具有副作用的參數(shù)所引起的問(wèn)題。  

#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
...
x = 5 ;
y = 8 ;
z = MAX ( x ++ , y ++ );
printf ( "x=%d y=%d z=%d\n" , x , y , z ); // 輸出的結(jié)果是什么?

這里我們得知道預(yù)處理器處理之后的結(jié)果是什么:

z = ( (x++) > (y++) ? (x++) : (y++));  

所以輸出的結(jié)果是:

x=6 y=10 z=9 

3.2.6 命名約定 

一般來(lái)講函數(shù)的宏的使用語(yǔ)法很相似。所以語(yǔ)言本身沒(méi)法幫我們區(qū)分二者。 那我們平時(shí)的一個(gè)習(xí)慣是:

把宏名全部大寫(xiě) 函數(shù)名不要全部大寫(xiě)

3.3 #undef  

這條指令用于移除一個(gè)宏定義。

3.4 命令行定義

許多 C 的編譯器提供了一種能力,允許在命令行中定義符號(hào)。用于啟動(dòng)編譯過(guò)程。

例如:當(dāng)我們根據(jù)同一個(gè)源文件要編譯出一個(gè)程序的不同版本的時(shí)候,這個(gè)特性有點(diǎn)用處。(假如某個(gè) 程序中聲明了一個(gè)某個(gè)長(zhǎng)度的數(shù)組,如果機(jī)器內(nèi)存有限,我們需要一個(gè)很小的數(shù)組,但是另外一個(gè)機(jī)器內(nèi)存大些,我們需要一個(gè)數(shù)組能夠大些。)

3.5 條件編譯

在編譯一個(gè)程序的時(shí)候我們?nèi)绻獙⒁粭l語(yǔ)句(一組語(yǔ)句)編譯或者放棄是很方便的。因?yàn)槲覀冇袟l件編譯指令。 比如說(shuō):

調(diào)試性的代碼,刪除可惜,保留又礙事,所以我們可以選擇性的編譯。

常見(jiàn)的條件編譯指令:

1.
#if 常量表達(dá)式
 //...
#endif
//常量表達(dá)式由預(yù)處理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
 //..
#endif
2.多個(gè)分支的條件編譯
#if 常量表達(dá)式
 //...
#elif 常量表達(dá)式
 //...
#else
 //...
#endif
3.判斷是否被定義
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)
 #ifdef OPTION1
 unix_version_option1();
 #endif
 #ifdef OPTION2
 unix_version_option2();
 #endif
#elif defined(OS_MSDOS)
 #ifdef OPTION2
 msdos_version_option2();
 #endif
#endif

注:這里#undef是取消#define的定義 

 #ifdef 是判斷有沒(méi)有進(jìn)行宏定義,如果沒(méi)有定義則就不執(zhí)行#ifdef里面的語(yǔ)句,#ifdef和#endif是配套使用的

總結(jié)

到此這篇關(guān)于C語(yǔ)言中程序環(huán)境和預(yù)處理的文章就介紹到這了,更多相關(guān)C語(yǔ)言程序環(huán)境和預(yù)處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac

    C++使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac

    mp4的音頻流通常是aac編碼,我們做音視頻采集的時(shí)候就需要將,采集的音頻PCM編碼成aac,本文就來(lái)為大家介紹一下C++如何使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac吧
    2023-11-11
  • VC++ 獲取系統(tǒng)時(shí)間的方法匯總

    VC++ 獲取系統(tǒng)時(shí)間的方法匯總

    本文給大家匯總介紹了5種VC++中獲取系統(tǒng)時(shí)間的方法,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。
    2015-07-07
  • C++實(shí)現(xiàn)哈夫曼編碼

    C++實(shí)現(xiàn)哈夫曼編碼

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)哈夫曼編碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++之智能指針初步及棄用auto_ptr的原因分析

    C++之智能指針初步及棄用auto_ptr的原因分析

    這篇文章主要介紹了C++之智能指針初步及棄用auto_ptr的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Qt與QWebEngineView交互完整參考示例代碼

    Qt與QWebEngineView交互完整參考示例代碼

    QWebEngineView是Qt框架中的一個(gè)組件,它是基于Chromium內(nèi)核的Web瀏覽器引擎,用于在Qt應(yīng)用程序中嵌入網(wǎng)頁(yè)內(nèi)容和實(shí)現(xiàn)各種Web應(yīng)用功能,這篇文章主要給大家介紹了關(guān)于Qt與QWebEngineView交互完整參考的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • Qt禁止程序多開(kāi)的實(shí)現(xiàn)示例

    Qt禁止程序多開(kāi)的實(shí)現(xiàn)示例

    本文主要介紹了Qt 禁止程序多開(kāi)的實(shí)現(xiàn)示例,主要介紹了三種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • C語(yǔ)言實(shí)現(xiàn)貪吃蛇代碼

    C語(yǔ)言實(shí)現(xiàn)貪吃蛇代碼

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)貪吃蛇代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • opencv學(xué)習(xí)筆記C++繪制灰度直方圖

    opencv學(xué)習(xí)筆記C++繪制灰度直方圖

    這篇文章主要為大家介紹了opencv學(xué)習(xí)筆記C++繪制灰度直方圖的實(shí)現(xiàn)代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Qt如何實(shí)現(xiàn)輸入框@聯(lián)系人的@檢測(cè)的示例

    Qt如何實(shí)現(xiàn)輸入框@聯(lián)系人的@檢測(cè)的示例

    本文主要介紹了Qt如何實(shí)現(xiàn)輸入框@聯(lián)系人的@檢測(cè)的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 求子數(shù)組最大和的解決方法詳解

    求子數(shù)組最大和的解決方法詳解

    本篇文章是對(duì)求子數(shù)組最大和的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論