A. c語言中預處理命令都有哪些
我們可以在C源程序中插入傳給編譯程序的各中指令,這些指令被稱為預處理器指令,它們擴充了程序設計的環境。現把常用的預處理命令總結如下:
1. 預處理程序
按照ANSI標準的定義,預處理程序應該處理以下指令:
#if #ifdef #ifndef #else #elif
#endif
#define
#undef
#line
#error
#pragma
#include
顯然,上述所有的12個預處理指令都以符號#開始,,每條預處理指令必須獨佔一行。
2. #define
#define指令定義一個標識符和一個串(也就是字元集),在源程序中發現該標識符時,都用該串替換之。這種標識符稱為宏名字,相應的替換稱為宏代換。一般形式如下:
#define macro-name char-sequence
這種語句不用分號結尾。宏名字和串之間可以有多個空白符,但串開始後只能以新行終止。
例如:我們使用LEFT代表1,用RIGHT代表0,我們使用兩個#define指令:
#define LEFT 1
#define RIGHT 0
每當在源程序中遇到LEFT或RIGHT時,編譯程序都用1或0替換。
定義一個宏名字之後,可以在其他宏定義中使用,例如:
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
宏代換就是用相關的串替代標識符。因此,如果希望定義一條標准錯誤信息時,可以如下定義:
#define ERROR_MS 「Standard error on input \n」
如果一個串長於一行,可在行尾用反斜線」\」續行,如下:
#define LONG_STRING 「This is a very very long \
String that is used as an example」
3. #error
#error指令強制編譯程序停止編譯,它主要用於程序調試。#error指令的一般形式是:
#error error-message
注意,宏串error-message不用雙引號包圍。遇到#error指令時,錯誤信息被顯示,可能同時還顯示編譯程序作者預先定義的其他內容。
4. #include
程序中的#include指令要求編譯程序讀入另一個源文件。被讀入文件的名字必須用雙引號(「」)或一對尖括弧(<>)包圍,例如:
#include 「stdio.h」
#include <stdio.h>
都使C編譯程序讀入並編譯頭文件以用於I/O系統庫函數。
包含文件中可以包含其他#include指令,稱為嵌套包含。允許的最大嵌套深度隨編譯器而變。
文件名被雙括弧或尖括弧包圍決定了對指定文件的搜索方式。文件名被尖括弧包圍時,搜索按編譯程序作者的定義進行,一般用於搜索某些專門放置包含文件的特殊目錄。當文件名被雙括弧包圍時,搜索按編譯程序實時的規定進行,一般搜索當前目錄。如未發現,再按尖括弧包圍時的辦法重新搜索一次。
通常,絕大多數程序員使用尖括弧包圍標準的頭文件,雙引號用於包圍與當前程序相關的文件名。
5. 條件編譯指令
若干編譯指令允許程序員有選擇的編譯程序源代碼的不同部分,這種過程稱為條件編譯。
5.1#if、#else、#elif #endif
條件編譯指令中最常用的或許是#if,#else,#elif和#endif。這些指令允許程序員根據常數表達式的結果有條件的包圍部分代碼。
#if的一般形式是:
#if constant-expression
Statement sequence
#endif
如#if後的常數表達式為真,則#if和#endif中間的代碼被編譯,否則忽略該代碼段。#endif標記#if塊的結束。
#else指令的作用與C語言的else相似,#if指令失敗時它可以作為備選指令。例如:
#include <stdio.h>
#define MAX 100
Int main(void)
{
#if MAX>99
printf(「Compiled for array greater than 99.\n」);
#else
printf(「Complied for small array.\n」);
#endif
return 0;
}
注意,#else既是標記#if塊的結束,也標記#else塊的開始。因為每個#if只能寫一個#endif匹配。
#elif指令的意思是「否則,如果」,為多重編譯選擇建立一條if-else-if(如果-否則-如果鏈)。如果#if表達式為真,該代碼塊被編譯,不測試其他#elif表達式。否則,序列中的下一塊被測試,如果成功則編譯之。一般形式如下:
#if expression
Statement sequence
#elif expression1
Statement sequence
#elif expression2
Statement sequence
.
.
.
#elif expression
Statement sequence
#endif
5.2#ifdef和#ifndef
條件編譯的另一個方法是使用編譯指令#ifdef和#ifndef,分別表示「如果已定義」和「如果未定義」。#ifdef的一般形式如下:
#ifdef macro-name
Statement sequence
#endif
如果macro-name原先已經被一個#define語句定義,則編譯其中的代碼塊。
#ifndef的一般形式是:
#ifndef macro-name
Statement sequence
#endif
如果macro-name當前未被#define語句定義,則編譯其中的代碼塊。
我認為,用這種,可以很方便的開啟/關閉整個程序的某項特定功能。
#ifdef和#ifndef都可以使用#else或#elif語句。
#inlucde <stdio.h>
#define T 10
Int main(void)
{
#ifdef t
Printf(「Hi T\n」);
#else
Printf(「Hi anyone\n」);
#endif
#ifndef M
Printf(「M Not Defined\n」);
#endif
Return 0;
}
6. #undef
#undef指令刪除前面定義的宏名字。也就是說,它「不定義」宏。一般形式為:
#undef macro-name
7. 使用defined
除#ifdef之外,還有另外一種確定是否定義宏名字的方法,即可以將#if指令與defined編譯時操作符一起使用。defined操作符的一般形式如下:
defined macro-name
如果macro-name是當前定義的,則表達式為真,否則為假。
例如,確定宏MY是否定義,可以使用下列兩種預處理命令之一:
#if defined MY
或
#ifdef MY
也可以在defined之前加上感嘆號」!」來反轉相應的條件。例如,只有在DEBUG未定義的情況下才編譯。
#if !defined DEBUG
Printf(「Final Version!\n」);
#endif
使用defined的一個原因是,它允許由#elif語句確定的宏名字存在。
8. #line
#line指令改變__LINE__和__FILE__的內容。__LINE__和__FILE__都是編譯程序中預定義的標識符。標識符__LINE__的內容是當前被編譯代碼行的行號,__FILE__的內容是當前被編譯源文件的文件名。#line的一般形式是:
#line number 「filename」
其中,number是正整數並變成__LINE__的新值;可選的「filename」是合法文件標識符並變成__FILE__的新值。#line主要用於調試和特殊應用。
9. #pragma
#pragma是編譯程序實現時定義的指令,它允許由此向編譯程序傳入各種指令。例如,一個編譯程序可能具有支持跟蹤程序執行的選項,此時可以用#pragma語句選擇該功能。編譯程序忽略其不支持的#pragma選項。#pragma提高C源程序對編譯程序的可移植性。
10. 預處理操作符#和##
有兩個預處理操作符:#和##,它們可以在#define中使用。
操作符#通常稱為字元串化的操作符,它把其後的串變成用雙引號包圍的串。例如:
#include <stdio.h>
#define mkstr(s) #s
int main(void)
{
Printf(mkstr(I like C));
Return 0;
}
預處理程序把以下的語句:
Printf(mkstr(I like C));
變成
Printf(「I like C」);
操作符##把兩個標記拼在一起,形成一個新標記。例如:
#include <stdio.h>
#define concat(a,a) a##b
int main(void)
{
Int xy = 10;
Printf(「%d」,concat(x,y));
Return 0;
}
預處理程序把以下語句:
Printf(「%d」,concat(x,y));
變成
Printf(「%d」,xy);
操作符#和##主要作用是允許預處理程序對付某些特殊情況,多數程序中並不需要。
11. 預定義宏
C規范了5個固有的預定義宏,它們是:
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__
__LINE__和__FILE__包含正在編譯的程序的行號和文件名。
__DATE__和內容形如month/day/year(月/日/年)的串,代表源文件翻譯成目標碼的日期。
__TIME__中的串代表源代碼編譯成目標碼的時間,形如hour:minute:second(時:分:秒)
如果__STDC__的內容是十進制常數1,則表示編譯程序的實現符合標准C。
B. C#中的預處理器命令是指什麼有什麼作用,能幹什麼
預處理器命令從來不會被翻譯為可執行代碼中的命令,但會影響編譯過程的各個方面。例如:使用預處理器指令可以禁止編譯器編譯代碼的某一部分,如果計劃發布兩個版本的代碼,即基本版本和有更多功能的企業版本,即可以使用這些預處理器指令。在編譯軟體的基本版本時,使用預處理器指令還可以禁止編譯器編譯於額外功能相關的代碼。另外,在編寫提供調試信息的代碼時,也可以使用預處理器指令。在銷售軟體時,一般不希望編譯這部分代碼。預處理器指令開頭都有符號#。
C. c程序在執行過程中對預處理命令進行處理這一說法為什麼是錯誤的
C語言在編譯前由預處理器對預處理命令進行處理,編譯時進行語法分析。執行過程就是運行程序。
程序設計語言的預處理的概念:在編譯之前進行的處理。
C語言的預處理主要有三個方面的內容:
1、宏定義;
2、文件包含;
3、條件編譯。 預處理命令以符號「#」開頭。
C程序的源代碼中可包括各種編譯指令,這些指令稱為預處理命令。雖然它們實際上不是C語言的一部分,但卻擴展了C程序設計的環境。本節將介紹如何應用預處理程序和注釋簡化程序開發過程,並提高程序的可讀性。
(3)編譯分為預處理器擴展閱讀
C語言無參數宏定義
在C語言源程序中允許用一個標識符來表示一個字元串,稱為「宏」。被定義為「宏」的標識符稱為「宏名」。在編譯預處理時,對程序中所有出現的「宏名」,都用宏定義中的字元串去代換,這稱為「宏代換」或「宏展開」。
宏定義是由源程序中的宏定義命令完成的。宏代換是由預處理程序自動完成的。在C語言中,「宏」分為有參數和無參數兩種。本節討論無參數宏。
無參宏的宏名後不帶參數。其定義的一般形式為:#define 標識符 字元串
其中的「#」表示這是一條預處理命令。凡是以「#」開頭的均為預處理命令。「define」為宏定義命令。「標識符」為所定義的宏名。「字元串」可以是常數、表達式、格式串等。
在前面介紹過的符號常量的定義就是一種無參宏定義。此外,常對程序中反復使用的表達式進行宏定義。例如:#define M (y*y+3*y)
D. #後面跟的是預處理何為預處理一定要放在程序的開頭嗎同樣是預處理順序能調換嗎
因為有些函數不是你自己定義的,像printf和scanf (頭文件為stdio.h),但是你調用他們的時候,程序去哪找呢,對,就是預處理是include進來的頭文件,預處理要放在程序的開頭,但是include的順序可以改變 ,當然你也可以把你自己寫的子函數放到自己編寫的頭文件中,然後include進來,和你直接在源文件中編寫是一樣的
E. c++中的編譯器和預處理器有何不同
元代碼中,包含了兩個部分的內容,
一個是對機器有用的東西,
一個是對人有用的東西,比如
注釋。
預處理器就是
在編譯之前,把代碼整理一下,把一些沒用的東西,給處理掉。做好准備工作後,然後再編譯。
F. 程序的編譯期,鏈接期, 運行期各執行哪些操作
參考一下:
源文件的編譯過程包含兩個主要階段,而它們之間的轉換是自動的。第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在文件中的預處理指令來修改源文件的內容。#include指令就是一個預處理指令,它把頭文件的內容添加到.cpp文件中還有其他許多預處理指令
這個在編譯之前修改源文件的方式提供了很大的靈活性,以適應不同的計算機和操作系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或操作系統是不同的。在許多情況下,可以把用於不同環境的代碼放在同一個文件中,再在預處理階段修改代碼,使之適應當前的環境。
預處理器顯示為一個獨立的操作,但一般不能獨立於編譯器來執行這個操作。調用編譯器會自動執行預處理過程,之後才編譯代碼。
編譯器為給定源文件輸出的是機器碼,執行這個過程需要較長時間。在對象文件之間並沒有建立任何連接。對應於某個源文件的對象文件包含在其他源文件中定義的函數引用或其他指定項的引用,而這些函數或項仍沒有被解析。同樣,也沒有建立同庫函數的鏈接。實際上,這些函數的代碼並不是文件的一部分。這些工作是由鏈接程序(有時稱為鏈接編輯器)完成的
鏈接程序把所有對象文件中的機器碼組合在一起,並解析它們之間的交叉引用。它還集成了對象模塊所使用的庫函數的代碼。這是鏈接程序的一種簡化表示,因為這里假定在可執行模塊中,模塊之間的所有鏈接都是靜態建立的。實際上有些鏈接是動態的,即這些鏈接是在程序執行時建立的。
鏈接程序靜態地建立函數之間的鏈接,即在程序執行之前建立組成程序的源文件中所包含的函數鏈接。動態建立的函數之間的鏈接(在程序執行過程中建立的鏈接)將函數編譯並鏈接起來,創建另一種可執行模塊—— 動態鏈接庫或共享庫。動態鏈接庫中的函數鏈接是在程序調用函數時才建立的,在程序調用之前,該鏈接是不存在的。
動態鏈接庫有幾個重要的優點。一個主要的優點是動態鏈接庫中的函數可以在幾個並行執行的程序之間共享,這將節省相同函數佔用的內存空間。另一個優點是動態鏈接庫在調用其中的函數之前是不會載入到內存中的。也就是說,如果不使用給定動態鏈接庫中的函數,該動態鏈接庫就不會佔用內存空間
G. 預處理類型
1. 預處理程序
按照ANSI標準的定義,預處理程序應該處理以下指令:
#if #ifdef #ifndef #else #elif
#endif
#define
#undef
#line
#error
#pragma
#include
顯然,上述所有的12個預處理指令都以符號#開始,,每條預處理指令必須獨佔一行。
2. #define
#define指令定義一個標識符和一個串(也就是字元集),在源程序中發現該標識符時,都用該串替換之。這種標識符稱為宏名字,相應的替換稱為宏代換。一般形式如下:
#define macro-name char-sequence
這種語句不用分號結尾。宏名字和串之間可以有多個空白符,但串開始後只能以新行終止。
例如:我們使用LEFT代表1,用RIGHT代表0,我們使用兩個#define指令:
#define LEFT 1
#define RIGHT 0
每當在源程序中遇到LEFT或RIGHT時,編譯程序都用1或0替換。
定義一個宏名字之後,可以在其他宏定義中使用,例如:
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
宏代換就是用相關的串替代標識符。因此,如果希望定義一條標准錯誤信息時,可以如下定義:
#define ERROR_MS 「Standard error on input \n」
如果一個串長於一行,可在行尾用反斜線」\」續行,如下:
#define LONG_STRING 「This is a very very long \
String that is used as an example」
3. #error
#error指令強制編譯程序停止編譯,它主要用於程序調試。#error指令的一般形式是:
#error error-message
注意,宏串error-message不用雙引號包圍。遇到#error指令時,錯誤信息被顯示,可能同時還顯示編譯程序作者預先定義的其他內容。
4. #include
程序中的#include指令要求編譯程序讀入另一個源文件。被讀入文件的名字必須用雙引號(「」)或一對尖括弧(<>)包圍,例如:
#include 「stdio.h」
#include 都使C編譯程序讀入並編譯頭文件以用於I/O系統庫函數。
包含文件中可以包含其他#include指令,稱為嵌套包含。允許的最大嵌套深度隨編譯器而變。
文件名被雙括弧或尖括弧包圍決定了對指定文件的搜索方式。文件名被尖括弧包圍時,搜索按編譯程序作者的定義進行,一般用於搜索某些專門放置包含文件的特殊目錄。當文件名被雙括弧包圍時,搜索按編譯程序實時的規定進行,一般搜索當前目錄。如未發現,再按尖括弧包圍時的辦法重新搜索一次。
通常,絕大多數程序員使用尖括弧包圍標準的頭文件,雙引號用於包圍與當前程序相關的文件名。
5. 條件編譯指令
若干編譯指令允許程序員有選擇的編譯程序源代碼的不同部分,這種過程稱為條件編譯。
5.1#if、#else、#elif #endif
條件編譯指令中最常用的或許是#if,#else,#elif和#endif。這些指令允許程序員根據常數表達式的結果有條件的包圍部分代碼。
#if的一般形式是:
#if constant-expression
Statement sequence
#endif
如#if後的常數表達式為真,則#if和#endif中間的代碼被編譯,否則忽略該代碼段。#endif標記#if塊的結束。
#else指令的作用與C語言的else相似,#if指令失敗時它可以作為備選指令。例如:
#include #define MAX 100
Int main(void)
{
#if MAX>99
printf(「Compiled for array greater than 99.\n」);
#else
printf(「Complied for small array.\n」);
#endif
return 0;
}
注意,#else既是標記#if塊的結束,也標記#else塊的開始。因為每個#if只能寫一個#endif匹配。
#elif指令的意思是「否則,如果」,為多重編譯選擇建立一條if-else-if(如果-否則-如果鏈)。如果#if表達式為真,該代碼塊被編譯,不測試其他#elif表達式。否則,序列中的下一塊被測試,如果成功則編譯之。一般形式如下:
#if expression
Statement sequence
#elif expression1
Statement sequence
#elif expression2
Statement sequence
.
.
.
#elif expression
Statement sequence
#endif
5.2#ifdef和#ifndef
條件編譯的另一個方法是使用編譯指令#ifdef和#ifndef,分別表示「如果已定義」和「如果未定義」。#ifdef的一般形式如下:
#ifdef macro-name
Statement sequence
#endif
如果macro-name原先已經被一個#define語句定義,則編譯其中的代碼塊。
#ifndef的一般形式是:
#ifndef macro-name
Statement sequence
#endif
如果macro-name當前未被#define語句定義,則編譯其中的代碼塊。
我認為,用這種,可以很方便的開啟/關閉整個程序的某項特定功能。
#ifdef和#ifndef都可以使用#else或#elif語句。
#inlucde #define T 10
Int main(void)
{
#ifdef t
Printf(「Hi T\n」);
#else
Printf(「Hi anyone\n」);
#endif
#ifndef M
Printf(「M Not Defined\n」);
#endif
Return 0;
}
6. #undef
#undef指令刪除前面定義的宏名字。也就是說,它「不定義」宏。一般形式為:
#undef macro-name
7. 使用defined
除#ifdef之外,還有另外一種確定是否定義宏名字的方法,即可以將#if指令與defined編譯時操作符一起使用。defined操作符的一般形式如下:
defined macro-name
如果macro-name是當前定義的,則表達式為真,否則為假。
例如,確定宏MY是否定義,可以使用下列兩種預處理命令之一:
#if defined MY
或
#ifdef MY
也可以在defined之前加上感嘆號」!」來反轉相應的條件。例如,只有在DEBUG未定義的情況下才編譯。
#if !defined DEBUG
Printf(「Final Version!\n」);
#endif
使用defined的一個原因是,它允許由#elif語句確定的宏名字存在。
8. #line
#line指令改變__LINE__和__FILE__的內容。__LINE__和__FILE__都是編譯程序中預定義的標識符。標識符__LINE__的內容是當前被編譯代碼行的行號,__FILE__的內容是當前被編譯源文件的文件名。#line的一般形式是:
#line number 「filename」
其中,number是正整數並變成__LINE__的新值;可選的「filename」是合法文件標識符並變成__FILE__的新值。#line主要用於調試和特殊應用。
9. #pragma
#pragma是編譯程序實現時定義的指令,它允許由此向編譯程序傳入各種指令。例如,一個編譯程序可能具有支持跟蹤程序執行的選項,此時可以用#pragma語句選擇該功能。編譯程序忽略其不支持的#pragma選項。#pragma提高C源程序對編譯程序的可移植性。
10. 預處理操作符#和##
有兩個預處理操作符:#和##,它們可以在#define中使用。
操作符#通常稱為字元串化的操作符,它把其後的串變成用雙引號包圍的串。例如:
#include #define mkstr(s) #s
int main(void)
{
Printf(mkstr(I like C));
Return 0;
}
預處理程序把以下的語句:
Printf(mkstr(I like C));
變成
Printf(「I like C」);
操作符##把兩個標記拼在一起,形成一個新標記。例如:
#include #define concat(a,a) a##b
int main(void)
{
Int xy = 10;
Printf(「%d」,concat(x,y));
Return 0;
}
預處理程序把以下語句:
Printf(「%d」,concat(x,y));
變成
Printf(「%d」,xy);
操作符#和##主要作用是允許預處理程序對付某些特殊情況,多數程序中並不需要。
11. 預定義宏
C規范了5個固有的預定義宏,它們是:
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__
__LINE__和__FILE__包含正在編譯的程序的行號和文件名。
__DATE__和內容形如month/day/year(月/日/年)的串,代表源文件翻譯成目標碼的日期。
__TIME__中的串代表源代碼編譯成目標碼的時間,形如hour:minute:second(時:分:秒)
如果__STDC__的內容是十進制常數1,則表示編譯程序的實現符合標准C。
H. c++中的編譯器和預處理器有何不同
元代碼中,包含了兩個部分的內容,
一個是對機器有用的東西,
一個是對人有用的東西,比如 注釋。
預處理器就是 在編譯之前,把代碼整理一下,把一些沒用的東西,給處理掉。做好准備工作後,然後再編譯。
I. C語言中 「編譯時處理」 與 「預處理」 兩個概念的區別
浩強哥的教材中說的很清楚,可以參考。簡單來說,C語言程序在編譯前,其實是有一個預備工作的,這個就是「預處理」,可以理解為:人類所編寫的程序,需要轉化為機器能夠編譯的合理輸入文件。機器編譯,就是按照語法來處理語句,一些語句或者邏輯是在編譯時才有意義,才進行分析,這就是「編譯時處理」。
J. 在預處理器macros,如何識別平台/編譯器
1.預處理首先源代碼文件(.c/.cpp)和相關頭文件(.h/.hpp)被預處理器cpp預編譯成.i文件(C++為.ii)。預處理命令為:gcc–Ehello.c–ohello.i預編譯過程主要處理那些源代碼中以#開始的預編譯指令,主要處理規則如下:u將所有的#define