版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第8章編譯預(yù)處理和動(dòng)態(tài)存儲(chǔ)分配8.1編譯預(yù)處理8.2宏定義8.3文件包含處理8.4動(dòng)態(tài)存儲(chǔ)分配8.1編譯預(yù)處理C語言允許在源程序中加入一些“預(yù)處理命令”(preprocessingdirective),以改進(jìn)程序設(shè)計(jì)環(huán)境,提高編程效率。這些預(yù)處理指令是由C標(biāo)準(zhǔn)建議的,但是它不是C語言本身的組成部分,不能用C編譯系統(tǒng)直接對(duì)它們進(jìn)行編譯(因?yàn)榫幾g程序不能識(shí)別它們)。所謂“編譯預(yù)處理”就是在C編譯程序?qū)源程序進(jìn)行編譯前,由編譯預(yù)處理程序?qū)@些編譯預(yù)處理命令行進(jìn)行處理的過程。在預(yù)處理階段,預(yù)處理器把程序中的注釋全部刪除;對(duì)預(yù)處理指令進(jìn)行處理,如把#include指令指定的頭文件(如stdio.h)的內(nèi)容復(fù)制到#include指令處;對(duì)#define指令,進(jìn)行指定的字符替換(如將程序中的符號(hào)常量用指定的字符串代替),同時(shí)刪去預(yù)處理指令。8.1編譯預(yù)處理經(jīng)過預(yù)處理后的程序不再包括預(yù)處理指令了,最后再由編譯程序?qū)︻A(yù)處理后的源程序進(jìn)行實(shí)際的編譯處理,得到可供執(zhí)行的目標(biāo)代碼。C語言與其他高級(jí)語言的一個(gè)重要區(qū)別是可以使用預(yù)處理指令和具有預(yù)處理的功能。C語言提供的預(yù)處理功能常用的主要有以下3種:1、宏定義;2、文件包含;3、條件編譯。這些預(yù)處理命令組成的預(yù)處理命令行必須在一行的開頭以”#”號(hào)開始,每行的末尾不得用“;”號(hào)結(jié)束,以區(qū)別于C語句、定義和說明語句。這些命令行的語法與C語言中其他部分的語法無關(guān)。根據(jù)需要,命令行可以出現(xiàn)在程序的任何一行的開始部位,其作用一直持續(xù)到源文件的末尾。8.2宏定義8.2.1不帶參數(shù)的宏定義8.2.2帶參數(shù)的宏定義8.2.3終止宏定義8.2.1不帶參數(shù)的宏定義1不帶參數(shù)的宏定義命令行形式格式:#define宏名替換文本或者:#define宏名在define、宏名和宏替換文本之間用空格隔開。例如:#define SIZE 100以上標(biāo)識(shí)符SIZE稱為“宏名”,是用戶定義的標(biāo)識(shí)符,因此,不得與程序中的其他名字相同。在編譯時(shí),在此命令行之后,預(yù)處理程序?qū)υ闯绦蛑械乃忻麨镾IZE的標(biāo)識(shí)符用100三個(gè)字符來替換,這個(gè)替換過程稱為“宏替換”。但要注意:不能認(rèn)為“SIZE等于整數(shù)100”。#define命令行可以不包含“替換文本”,這種情況下僅說明標(biāo)識(shí)符“被定義”。8.2.1不帶參數(shù)的宏定義2替換文本中可以包含已定義過的宏名例8.1計(jì)算圓面積。#include<stdio.h>#definePI3.1415926#defineR3.0#defineSPI*R*R /*S的宏定義使用了前面的PI和R宏定義*/intmain(){
printf(“圓的面積=%f”,S); return0;}運(yùn)行結(jié)果:圓的面積=28.274333分析:該例中既有宏定義,又有宏定義的多重替換,這樣求圓的面積,只需將宏名S進(jìn)行展開后計(jì)算,輸出即可。8.2.1不帶參數(shù)的宏定義3當(dāng)宏定義在一行中寫不下,需要在下一行繼續(xù)時(shí),只需在最后一個(gè)字符后緊接著加一個(gè)反斜線“\”。例如:#define LEAP_YEAR year%4==0\&&year%100!=0||year%400==0第一列如果在“\”前或在下一行的開頭留有許多空格,則在宏替換時(shí)也將加入這些空格。4同一個(gè)宏名不能重復(fù)定義,除非兩個(gè)宏定義命令行完全一致。5替換文本不能替換雙引號(hào)中與宏名相同的字符串。例8.2宏名相同的字符串不能替換。#define BOOK “TheRedandTheBlack”intmain(){
printf(“%s\n”,”BOOK”); return0;}運(yùn)行結(jié)果:BOOK8.2.1不帶參數(shù)的宏定義6替換文本并不替換用戶標(biāo)識(shí)符中的成分。例如,宏名YES,不會(huì)替換標(biāo)識(shí)符YESORNO中的YES。7用作宏名的標(biāo)識(shí)符通常用大寫字母表示,這并不是語法規(guī)定,只是一種習(xí)慣,以便與程序中的其他標(biāo)識(shí)符相區(qū)別。8在C程序中,宏定義的定義位置一般寫在程序的開頭。返回8.2.2帶參數(shù)的宏定義1帶參數(shù)的宏定義命令行形式如下:格式:#define 宏名(形參表) 替換文本如果定義帶參數(shù)的宏,在對(duì)源程序進(jìn)行預(yù)處理時(shí),將程序中出現(xiàn)宏名的地方均用替換文本替換,并用實(shí)參代替替換文本中的形參。例8.3編寫程序,使用帶參數(shù)的宏定義。#include<stdio.h>#defineMAX(a,b) a>b?a:b /*定義帶參數(shù)的宏MAX*/#defineSQR(c)c*c /*定義帶參數(shù)的宏SQR*/intmain(){
intx=3,y=4; x=MAX(x,y);
y=SQR(x);
printf(“x=%d,y=%d\n”,x,y);
return0;}運(yùn)行結(jié)果:x=4,y=16對(duì)于帶參的宏定義有以下問題需要說明:2.帶參宏定義中,宏名和形參表之間不能有空格出現(xiàn)。例如把:
#defineMAX(a,b)(a>b)?a:b寫為:
#defineMAX(a,b)(a>b)?a:b將被認(rèn)為是無參宏定義,宏名MAX代表字符串(a,b)(a>b)?a:b。宏展開時(shí),宏調(diào)用語句:
max=MAX(x,y);將變?yōu)椋?/p>
max=(a,b)(a>b)?a:b(x,y);這顯然是錯(cuò)誤的。8.2.2帶參數(shù)的宏定義3.在帶參宏定義中,形式參數(shù)不分配內(nèi)存單元,因此不必作類型定義。而宏調(diào)用中的實(shí)參有具體的值。要用它們?nèi)ゴ鷵Q形參,因此必須作類型說明。這是與函數(shù)中的情況不同的。在函數(shù)中,形參和實(shí)參是兩個(gè)不同的量,各有自己的作用域,調(diào)用時(shí)要把實(shí)參值賦予形參,進(jìn)行“值傳遞”。而在帶參宏中,只是符號(hào)代換,不存在值傳遞的問題。4.在宏定義中的形參是標(biāo)識(shí)符,而宏調(diào)用中的實(shí)參可以是表達(dá)式。例8.4宏調(diào)用實(shí)參為表達(dá)式。#defineSQ(y)(y)*(y)main(){
int
a,sq;
printf("inputanumber:");
scanf("%d",&a);sq=SQ(a+1);printf("sq=%d\n",sq);}運(yùn)行結(jié)果:inputanumber:3sq=16分析:上例中第一行為宏定義,形參為y。程序第七行宏調(diào)用中實(shí)參為a+1,是一個(gè)表達(dá)式,在宏展開時(shí),用a+1代換y,再用(y)*(y)代換SQ,得到如下語句:
sq=(a+1)*(a+1);這與函數(shù)的調(diào)用是不同的,函數(shù)調(diào)用時(shí)要把實(shí)參表達(dá)式的值求出來再賦予形參。而宏代換中對(duì)實(shí)參表達(dá)式不作計(jì)算直接地照原樣代換。8.2.2帶參數(shù)的宏定義5.在宏定義中,字符串內(nèi)的形參通常要用括號(hào)括起來以避免出錯(cuò)。在上例中的宏定義中(y)*(y)表達(dá)式的y都用括號(hào)括起來,因此結(jié)果是正確的。如果去掉括號(hào),把程序改為以下形式:例8.5#defineSQ(y)y*ymain(){
int
a,sq;
printf("inputanumber:");
scanf("%d",&a);sq=SQ(a+1);printf("sq=%d\n",sq);}運(yùn)行結(jié)果:inputanumber:3sq=7分析:同樣輸入3,但結(jié)果卻是不一樣的。問題在哪里呢?這是由于代換只作符號(hào)代換而不作其它處理而造成的。宏代換后將得到以下語句:
sq=a+1*a+1;由于a為3故sq的值為7。這顯然與題意相違,因此參數(shù)兩邊的括號(hào)是不能少的。即使在參數(shù)兩邊加括號(hào)還是不夠的,請(qǐng)看下面程序:8.2.2帶參數(shù)的宏定義例8.6#defineSQ(y)(y)*(y)main(){
int
a,sq;
printf("inputanumber:");
scanf("%d",&a);sq=160/SQ(a+1);printf("sq=%d\n",sq);}運(yùn)行結(jié)果:inputanumber:3sq=160分析:本程序與前例相比,只把宏調(diào)用語句改為:
sq=160/SQ(a+1);運(yùn)行本程序如輸入值仍為3時(shí),希望結(jié)果為10。為什么會(huì)得這樣的結(jié)果呢?分析宏調(diào)用語句,在宏代換之后變?yōu)椋?/p>
sq=160/(a+1)*(a+1);a為3時(shí),由于“/”和“*”運(yùn)算符優(yōu)先級(jí)和結(jié)合性相同,則先作160/(3+1)得40,再作40*(3+1)最后得160。為了得到正確答案應(yīng)在宏定義中的整個(gè)字符串外加括號(hào),程序修改如例8.78.2.2帶參數(shù)的宏定義6帶參的宏和帶參函數(shù)很相似,但有本質(zhì)上的不同,除上面已談到的各點(diǎn)外,把同一表達(dá)式用函數(shù)處理與用宏處理兩者的結(jié)果有可能是不同的。例8.8main(){
inti=1;
while(i<=5)
printf("%d\n",SQ(i++));}SQ(inty){return((y)*(y));}例8.9#defineSQ(y)((y)*(y))main(){
inti=1;
while(i<=5)
printf("%d\n",SQ(i++));}例8.8運(yùn)行結(jié)果:1491625例8.9運(yùn)行結(jié)果:19258.2.2帶參數(shù)的宏定義7宏定義也可用來定義多個(gè)語句,在宏調(diào)用時(shí),把這些語句又代換到源程序內(nèi)。看下面的例子。例8.10#defineSSSV(s1,s2,s3,v)s1=l*w;s2=l*h;s3=w*h;v=w*l*h;main(){
intl=3,w=4,h=5,sa,sb,sc,vv;
SSSV(sa,sb,sc,vv);
printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);}運(yùn)行結(jié)果:sa=12sb=15sc=20vv=60分析:程序第一行為宏定義,用宏名SSSV表示4個(gè)賦值語句,4個(gè)形參分別為4個(gè)賦值符左部的變量。在宏調(diào)用時(shí),把4個(gè)語句展開并用實(shí)參代替形參。使計(jì)算結(jié)果送入實(shí)參之中。返回8.2.3終止宏定義可以用#undef提前終止宏定義的作用域。例如:#definePI3.14main()#undefPI以上PI的作用域從#definePI3.14命令行開始,到#undefPI命令行結(jié)束。從#undef以后PI變成無定義,不再代表3.14了。8.3文件包含處理所謂文件包含,是指在一個(gè)文件中,去包含另一個(gè)文件的全部內(nèi)容。C語言用#include命令行來實(shí)現(xiàn)文件包含的功能。格式:#include “文件名”或 #include <文件名>在預(yù)編譯時(shí),預(yù)編譯程序?qū)⒂弥付ㄎ募械膬?nèi)容來替換此命令行。如果文件名用雙引號(hào)括起來,系統(tǒng)先在源程序所在的目錄內(nèi)查找指定的包含文件,如果找不到,再按照系統(tǒng)指定的標(biāo)準(zhǔn)方式到有關(guān)目錄中去尋找;如果文件名用尖括號(hào)括起來,系統(tǒng)將直接按照系統(tǒng)指定的標(biāo)準(zhǔn)方式到有關(guān)目錄中尋找。說明:1包含文件的#include命令行通常應(yīng)書寫在所用源程序文件的開頭,故有時(shí)也把包含文件稱作“頭文件“。頭文件名可以由用戶指定,其后綴不一定用”.h”。2包含文件中,一般包含有一些公用的#define命令行、外部說明或?qū)Γ◣欤┖瘮?shù)的原型說明。例如stdio.h就是這樣的頭文件。3當(dāng)包含文件修改后,對(duì)包含該文件的源程序必須重新進(jìn)行編譯連接。4在一個(gè)程序中,允許有任意多個(gè)#include命令行。5在包含文件中還可以包含其他文件。8.4動(dòng)態(tài)存儲(chǔ)分配8.4.1malloc函數(shù)和free函數(shù)8.4.2calloc函數(shù)8.4.1malloc函數(shù)和free函數(shù)1malloc函數(shù)格式:(類型說明符*)malloc(size)功能:在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一塊長度為"size"字節(jié)的連續(xù)區(qū)域。函數(shù)的返回值為該區(qū)域的首地址。“類型說明符”表示把該區(qū)域用于何種數(shù)據(jù)類型。(類型說明符*)表示把返回值強(qiáng)制轉(zhuǎn)換為該類型指針?!皊ize”是一個(gè)無符號(hào)數(shù)。假設(shè)shortint型數(shù)據(jù)占2個(gè)字節(jié),float型數(shù)據(jù)占4字節(jié)存儲(chǔ)單元,則以下程序段將使pi指向一個(gè)shortint類型的存儲(chǔ)單元,使pf指向一個(gè)float類型的存儲(chǔ)單元:shortint*pi;float*pf;pi=(short*)malloc(2);pf=(float*)malloc(4);由于在ANSIC中malloc函數(shù)返回的指針為void*(無值型),故在調(diào)用函數(shù)時(shí),必須利用強(qiáng)制類型轉(zhuǎn)換將其轉(zhuǎn)成所需的類型。上面的程序段中,調(diào)用malloc函數(shù)時(shí)括號(hào)中的*號(hào)不可少,否則就轉(zhuǎn)換成普通變量類型而不是指針類型了。在動(dòng)態(tài)申請(qǐng)存儲(chǔ)空間時(shí),若不能確定數(shù)據(jù)類型所占字節(jié)數(shù),可以使用sizeof運(yùn)算符來求得。例如:
pi=(int*)malloc(sizeof(int)); pf=(float*)malloc(sizeof(float));這是一種常用的形式。此時(shí)將由系統(tǒng)來計(jì)算指定類型的字節(jié)數(shù),采用這種形式將有利于程序的移植。8.4.1malloc函數(shù)和free函數(shù)2free函數(shù)格式:free(void*ptr);功能:釋放ptr所指向的一塊內(nèi)存空間,ptr是一個(gè)任意類型的指針變量,它指向被釋放區(qū)域的首地址。被釋放區(qū)應(yīng)是由malloc或calloc函數(shù)所分配的區(qū)域。例8.11分配一塊區(qū)域,輸入一個(gè)學(xué)生數(shù)據(jù)。main(){
struct
stu{
intnum;char*name;charsex;floatscore;}*ps;
ps=(struct
stu*)malloc(sizeof(struct
stu));
ps->num=102;
ps->name="Zhangping";
ps->sex='M';
ps->score=62.5;
printf("Number=%d\nName=%s\n",ps->num,ps->name);
printf("Sex=%c\nScore=%f\n",ps->sex,ps->score);
free(ps);}運(yùn)行結(jié)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度跨境電商倉儲(chǔ)租賃合同合法經(jīng)營拓展全球市場(chǎng)4篇
- 二零二五年度建筑工地鋼筋施工安全培訓(xùn)合同
- 二零二五版網(wǎng)絡(luò)短視頻剪輯師招聘合同范本3篇
- 二零二五年度建筑用沙子購銷及環(huán)保審計(jì)合同3篇
- 2025年皮包原材料進(jìn)口合同二零二五年度版4篇
- 二零二五年度拍賣會(huì)籌備及組織服務(wù)合同4篇
- 2025年度牛羊肉品牌保護(hù)及侵權(quán)糾紛處理合同
- 二零二五年度內(nèi)墻抹灰工程質(zhì)量監(jiān)督合同范例
- 二零二五版摩托車二手車交易評(píng)估與收購合同4篇
- 2025年建筑物清潔與智能安防系統(tǒng)維護(hù)合同3篇
- 2024-2025學(xué)年北京石景山區(qū)九年級(jí)初三(上)期末語文試卷(含答案)
- 第一章 整式的乘除 單元測(cè)試(含答案) 2024-2025學(xué)年北師大版數(shù)學(xué)七年級(jí)下冊(cè)
- 春節(jié)聯(lián)歡晚會(huì)節(jié)目單課件模板
- 中國高血壓防治指南(2024年修訂版)
- 糖尿病眼病患者血糖管理
- 抖音音樂推廣代運(yùn)營合同樣本
- 教育促進(jìn)會(huì)會(huì)長總結(jié)發(fā)言稿
- 北師大版(2024新版)七年級(jí)上冊(cè)數(shù)學(xué)第四章《基本平面圖形》測(cè)試卷(含答案解析)
- 心理調(diào)適教案調(diào)整心態(tài)積極應(yīng)對(duì)挑戰(zhàn)
- 小學(xué)數(shù)學(xué)6年級(jí)應(yīng)用題100道附答案(完整版)
- 噴漆外包服務(wù)合同范本
評(píng)論
0/150
提交評(píng)論