?
目錄
翻譯環(huán)境?
linux下的測試??編輯
預(yù)定義符號
執(zhí)行環(huán)境
#define定義宏
#和##
#
##
宏參數(shù)的副作用
宏和函數(shù)對比
優(yōu)點(diǎn)
缺點(diǎn)
#undef?
?條件編譯
頭文件包含
在標(biāo)準(zhǔn)c的任何實(shí)現(xiàn)中,存在兩種環(huán)境——翻譯環(huán)境和執(zhí)行環(huán)境
翻譯環(huán)境?
翻譯環(huán)境生成目標(biāo)文件(.obj):
linux下的測試?
預(yù)定義符號
__FILE__ ? ? ?//進(jìn)行編譯的源文件
__LINE__ ? ? //文件當(dāng)前的行號
__DATE__ ? ?//文件被編譯的日期
__TIME__ ? ?//文件被編譯的時(shí)間
__STDC__ ? ?//如果編譯器遵循ANSI C,其值為1,否則未定義
vs不完全支持c標(biāo)準(zhǔn),Linux下的gcc支持c標(biāo)準(zhǔ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),存儲函數(shù)的局部變量和返回地址。程序同時(shí)也可以使用靜態(tài)(static )內(nèi)存,存儲于靜態(tài)內(nèi)存中的變量在程序的整個(gè)執(zhí)行過程 一直保留他們的值。4. 終止程序。正常終止 main 函數(shù);也有可能是意外終止。
#define定義宏
#define name( parament-list ) stuff其中的 parament - list 是一個(gè)由逗號隔開的符號表,它們可能出現(xiàn)在 stuff 中。
注意:參數(shù)列表的 左括號必須與name緊鄰 。如果兩者之間有任何空白存在,參數(shù)列表就會被解釋為 stuff 的一部分。
#define SQUARE(X) X*X//err
SQUARE(5+1)--->5+1*5+1
//正確寫法:
#define SQUARE(X) ((X)*(X))
注意:1. 宏參數(shù)和 #define 定義中可以出現(xiàn)其他 #define 定義的符號(優(yōu)先替換)。但是對于宏,不能出現(xiàn)遞歸。2. 當(dāng)預(yù)處理器搜索 #define 定義的符號的時(shí)候,字符串常量的內(nèi)容并不被搜索
#define SQUARE(X) ((X)*(X))
#define X 2//正確
#和##
#
當(dāng)我們想實(shí)現(xiàn)下面這串代碼時(shí):
int a = 10;
printf("the value of a is %d\n", a);
int b = 20;
printf("the value of b is %d\n", b);
float f = 3.5f;
printf("the value of f is %f\n", f);
有沒有什么更簡介的辦法呢?
我們知道,c語言可以對字符串進(jìn)行拼接,比如:
printf("hello" "world");
//輸出helloworld,省略了中間的空格。
修改后:
#define PRINT(val,format) printf("the value of "#val "is " format "\n",val)
int a = 10;
PRINT(a, "%d");
int b = 20;
PRINT(b, "%d");
float f = 3.5f;
PRINT(f, "%f");
這里的#val相當(dāng)于先對val完成替換再使之成為一個(gè)字符串("a")
##
## 可以把位于它兩邊的符號合成一個(gè)符號。它允許宏定義從分離的文本片段創(chuàng)建標(biāo)識符
宏參數(shù)的副作用
如果宏的參數(shù)在宏的定義中出現(xiàn)超過一次的話,如果參數(shù)帶有副作用,將會導(dǎo)致不可預(yù)測的結(jié)果。
#define MAX(x,y) ((x)>(y)?(x):(y))
int main()
{
int a = 3;
int b = 4;
int m = MAX(++a, ++b);
int m = ((++a) > (++b) ? (++a) : (++b));
printf("m = %d a=%d b=%d\n", m, a, b);
return 0;
}
?輸出結(jié)果為6,4,6
宏和函數(shù)對比
優(yōu)點(diǎn)
????????用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實(shí)際執(zhí)行這個(gè)小型計(jì)算工作所需要的時(shí)間更多。 所以宏比函數(shù)在程序的規(guī)模和速度方面更勝一籌。????????更為重要的是函數(shù)的參數(shù)必須聲明為特定的類型。所以函數(shù)只能在類型合適的表達(dá)式上使用。反之這個(gè)宏怎可以適用于整形、長整型、浮點(diǎn)型等可以 用于> 來比較的類型。
?
#define MALLOC(type,num) (type)malloc(sizeof(type)*num)
int* p = MALLOC(int*,4);//define實(shí)現(xiàn)自定義封裝
缺點(diǎn)
1.宏不能調(diào)試。
2.宏可能會帶來運(yùn)算符優(yōu)先級問題。
3.宏由于類型無關(guān),可能會導(dǎo)致程序不嚴(yán)謹(jǐn)。
4.如果宏定義的代碼量過大,可能會大幅增加程序的長度。
?
#undef?
作用:移去#define定義的對象
?
命令行定義
此方法適用于linux操作系統(tǒng)用命令的方式在程序編譯的時(shí)候?qū)ξ炊x的變量進(jìn)行定義的一種方式。?
#include <stdio.h>
int main()
{
? ?int array [ARRAY_SIZE];
? ?int i = 0;
? ?for(i = 0; i< ARRAY_SIZE; i ++)
? {
? ? ? ?array[i] = i;
? }
? ?for(i = 0; i< ARRAY_SIZE; i ++)
? {
? ? ? ?printf("%d " ,array[i]);
? }
? ?printf("\n" );
? ?return 0;
}
?命令行:
gcc test.c -D ARRAY_SIZE=10?
?條件編譯
在編譯一個(gè)程序的時(shí)候我們?nèi)绻獙⒁粭l語句(一組語句)編譯或者放棄是很方便的。因?yàn)槲覀冇袟l件 編譯指令
常見的條件編譯語句:
#if 常量表達(dá)式
//...
#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
與if..else很相似,不同的是條件編譯會把不滿足條件的代碼在預(yù)處理階段直接刪除掉。?
頭文件包含
本地文件包含:
#include "filename"
庫文件包含:
#include <stdio.h>
嵌套包含:
解決方案:
開頭寫:文章來源:http://www.zghlxwxcb.cn/news/detail-719784.html
#prama once
或者文章來源地址http://www.zghlxwxcb.cn/news/detail-719784.html
#ifndef __TEST_H__
#define __TEST_H__
//頭文件的內(nèi)容
#endif
到了這里,關(guān)于程序的編譯和鏈接的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!