最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

2. 詳解編譯+鏈接 

2.1 翻譯環(huán)境

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

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

2.2 編譯本身也分為幾個階段

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

2.3 運行環(huán)境  

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

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

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

3. 開始執(zhí)行程序代碼。這個時候程序將使用一個運行時堆棧(stack),存儲函數(shù)的局部變量和返回地址。程序同時也可以使用靜態(tài)(static )內存,存儲于靜態(tài)內存中的變量在程序的整個執(zhí)行過程一直保留他們的值。

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

3. 預處理詳解

3.1 預定義符號

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

舉個栗子:這些預定義符號都是內置的

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

這兩個預定義符號會在屏幕打印出源文件路徑,和該代碼在哪一行 

3.2 #define

3.2.1 #define 定義標識符

提問: 在define定義標識符的時候,要不要在最后加上 ; ? 比如:

#define MAX 1000;
#define MAX 1000

建議不要加上 ; ,這樣容易導致問題。

比如下面的場景:

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

 這里會出現(xiàn)語法錯誤。

3.2.2 #define 定義宏 

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

宏(define macro)。

下面是宏的申明方式:

#define name( parament - list ) stuff

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

注意:

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

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

如:

#define SQUARE( x ) x * x

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

置于程序中,預處理器就會用下面這個表達式替換上面的表達式。

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

3.2.3 #define 替換規(guī)則

在程序中擴展 #define 定義符號和宏時,需要涉及幾個步驟。

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

3.2.4 #和##  

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

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

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

這里輸出的是不是

hello bit ?

答案是確定的:是。

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

1.使用 # , 把一個宏參數(shù)變成對應的字符串

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

最終的輸出的結果應該是:

the value of i + 3 is 13

## 的作用 

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

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

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

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

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

#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 ); // 輸出的結果是什么?

這里我們得知道預處理器處理之后的結果是什么:

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

所以輸出的結果是:

x=6 y=10 z=9 

3.2.6 命名約定 

一般來講函數(shù)的宏的使用語法很相似。所以語言本身沒法幫我們區(qū)分二者。 那我們平時的一個習慣是:

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

3.3 #undef  

這條指令用于移除一個宏定義。

3.4 命令行定義

許多 C 的編譯器提供了一種能力,允許在命令行中定義符號。用于啟動編譯過程。

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

3.5 條件編譯

在編譯一個程序的時候我們如果要將一條語句(一組語句)編譯或者放棄是很方便的。因為我們有條件編譯指令。 比如說:

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

常見的條件編譯指令:

1.
#if 常量表達式
 //...
#endif
//常量表達式由預處理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
 //..
#endif
2.多個分支的條件編譯
#if 常量表達式
 //...
#elif 常量表達式
 //...
#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 是判斷有沒有進行宏定義,如果沒有定義則就不執(zhí)行#ifdef里面的語句,#ifdef和#endif是配套使用的

總結

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

相關文章

  • C++設計模式之觀察者模式

    C++設計模式之觀察者模式

    這篇文章主要介紹了C++設計模式之觀察者模式,本文講解了什么是觀察者模式、觀察者模式的UML類圖、觀察者模式的使用場合等內容,需要的朋友可以參考下
    2014-10-10
  • C++實現(xiàn)LeetCode(80.有序數(shù)組中去除重復項之二)

    C++實現(xiàn)LeetCode(80.有序數(shù)組中去除重復項之二)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(80.有序數(shù)組中去除重復項之二),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-07-07
  • C++調用EasyX庫實現(xiàn)嫦娥奔月小游戲

    C++調用EasyX庫實現(xiàn)嫦娥奔月小游戲

    這篇文章主要為大家詳細介紹了C++如何調用EasyX庫編寫一個簡單的嫦娥奔月小游戲,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下
    2023-09-09
  • C++ 位運算的具體實現(xiàn)

    C++ 位運算的具體實現(xiàn)

    位運算直接對內存數(shù)據(jù)進行操作,不需要轉換成十進制,因此處理速度非???本文主要介紹了C++ 位運算的具體實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • C++學習之異常機制詳解

    C++學習之異常機制詳解

    C++中的異常處理機制可以幫助我們處理程序在運行時可能會遇到的異常情況,比如內存分配錯誤、文件打開失敗等。本文就和大家詳細講講C++中異常機制的具體使用吧
    2023-04-04
  • C/C++中派生類訪問屬性詳解及其作用介紹

    C/C++中派生類訪問屬性詳解及其作用介紹

    這篇文章主要介紹了C/C++中派生類訪問屬性詳解及其作用介紹,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Matlab實現(xiàn)好看的配對箱線圖的繪制

    Matlab實現(xiàn)好看的配對箱線圖的繪制

    配對箱線圖,常見于配對樣本的數(shù)據(jù)分析中,它除了能夠表現(xiàn)兩組的整體差異,還能夠清晰地呈現(xiàn)單個樣本的前后改變。本文將用Matlab實現(xiàn)配對箱線圖的繪制,需要的可以參考一下
    2022-08-08
  • C語言SetConsoleTextAttribute函數(shù)使用方法

    C語言SetConsoleTextAttribute函數(shù)使用方法

    這篇文章介紹了C語言SetConsoleTextAttribute函數(shù)的使用方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-12-12
  • 深入解析C++編程中的運算符重載

    深入解析C++編程中的運算符重載

    這篇文章主要介紹了C++編程中的運算符重載,運算符重載是C++入門學習中的基礎知識,需要的朋友可以參考下
    2016-04-04
  • Matlab實現(xiàn)三維投影繪制的示例代碼

    Matlab實現(xiàn)三維投影繪制的示例代碼

    這篇文章系小編為大家?guī)砹艘粋€三維投影繪制函數(shù)(三視圖繪制),函數(shù)支持三維曲線、曲面、三維多邊形、參數(shù)方程曲線、參數(shù)方程曲面的投影繪制,需要的可以參考一下
    2022-08-08

最新評論

苍梧县| 正宁县| 阜城县| 宣汉县| 黔江区| 台东市| 中西区| 泰和县| 庆云县| 饶阳县| 甘孜县| 建德市| 道孚县| 尉犁县| 蛟河市| 岗巴县| 娱乐| 始兴县| 红河县| 应用必备| 武威市| 阿拉尔市| 乐业县| 怀集县| 调兵山市| 吉安县| 罗山县| 车险| 织金县| 和硕县| 横山县| 金堂县| 栾川县| 凌源市| 绿春县| 鹤岗市| 南皮县| 县级市| 通城县| 龙游县| 呈贡县|