最近看到自己之前剛開始學(xué)習(xí)的時(shí)候記的一些筆記就稍微整理了一下
第一章
c語言注釋
概念:給代碼進(jìn)行解釋說明
作用:加強(qiáng)程序代碼的可讀性和維護(hù)性
/*:多行注釋
//:單行注釋
變量和基本數(shù)據(jù)類型
變量:一塊存儲空間裆站,里面寫了相應(yīng)類型的值,通過變量來獲取里面的值
變量的本質(zhì):內(nèi)存的存儲單元
變量的過程:
1)聲明變量->開辟空間
2)初始化變量:向空間里寫內(nèi)容
3)使用變量:從空間里面讀取內(nèi)容
數(shù)據(jù)類型:int char float double
sizeof(數(shù)據(jù)類型名)顯示每種類型的字節(jié)數(shù)
變量命名:
以字母和下劃線做為開頭,由字母和下劃線和數(shù)字組成宏胯,大小寫敏感羽嫡,不能用c語言關(guān)鍵字比如:int、float肩袍、const杭棵、printf等。
變量初始化3種方式:
1)聲明的同時(shí)進(jìn)行初始化
2)運(yùn)行時(shí)用賦值表達(dá)式初始化
3)用戶輸入數(shù)值進(jìn)行初始化
變量前添加const是只讀變量的意思:一般我們會直接稱作“常量”氛赐,但是其實(shí)更準(zhǔn)確的稱為只讀變量魂爪。位置:內(nèi)存堆棧。只讀的性質(zhì)由編譯器賦予艰管,人為修改編譯不過滓侍。?只讀變量需要初始化,不然編譯會報(bào)錯(cuò)牲芋,因?yàn)槎x性聲明時(shí)如果不初始化撩笆,之后不允許初始化,這個(gè)變量就沒有意義了街图。
輸入浇衬,輸出printf scarf
標(biāo)準(zhǔn)的輸入與輸出:
? ? 包含頭文件
? ? 輸出:printf(".....\n",list...);
? ? 內(nèi)存——>顯示器
? ? 輸入:scanf("......",address list...);
? ? 鍵盤——>內(nèi)存
類型定義符
typedef關(guān)鍵字:給已有類型起別名
第二章
表達(dá)式=操作數(shù)+運(yùn)算符
操作數(shù):變量&常量
算數(shù)運(yùn)算符
二元運(yùn)算符+懒构、-餐济、*、/
除法運(yùn)算:操作數(shù)分母不能為0
兩整數(shù)相除胆剧,其值取整絮姆,小數(shù)忽略
取余:操作數(shù)分母不能為0;
操作數(shù)必須為整數(shù)秩霍,
自增自減前置++i --i 后置i++ i--
一元
sizeof:類型所占字節(jié)
關(guān)系運(yùn)算符&邏輯運(yùn)算符
邏輯:只有兩個(gè)值trun false
關(guān)系:<= > < >= == !=
一元否定:(!valid)
三目運(yùn)算符:(表達(dá)式1篙悯?表達(dá)式2:表達(dá)式3)
類型轉(zhuǎn)換:
? 顯示轉(zhuǎn)型:(被轉(zhuǎn)換的數(shù)據(jù)類型)變量
? 隱式轉(zhuǎn)型:低->高
? ? ? ? ? ? 賦值表達(dá)式:右-->左
? ? ? ? ? ? 邏輯數(shù)據(jù)<->int
? ? ? ? ? ? char <->int
第三章 控制流:
? 順序結(jié)構(gòu):表達(dá)式+分號 ? ? ?int a =10;
? ? ? ? ? ? 程序塊 {}
? 選擇結(jié)構(gòu):if:單路選擇
? ? ? ? ? ? if else:雙路選擇
? ? ? ? ? ? if... else if ...:多路選擇
? ? ? ? ? ? switch(條件表達(dá)式):case 表達(dá)式:語句;
? 循環(huán)結(jié)構(gòu):
? ? ? ? ? 前置測試循環(huán):先判斷铃绒,再執(zhí)行
? ? ? ? ? for表達(dá)式:?
? ? ? ? ? for(表達(dá)式1;表達(dá)式2;表達(dá)式3){......}
? ? ? ? ? while表達(dá)式:
? ? ? ? ? while(表達(dá)式2)
? ? ? ? ? {
? ? ? ? ? ? 循環(huán)體語句;
? ? ? ? ? ? 表達(dá)式3;
? ? ? ? ? }
? ? ? ? ? 后置測試循環(huán):先執(zhí)行鸽照,再判斷?
? ? ? ? ? do-while 表達(dá)式:
? ? ? ? ? do
? ? ? ? ? {
? ? ? ? ? ? 循環(huán)體語句;
? ? ? ? ? ? 表達(dá)式3;?
? ? ? ? ? }while(表達(dá)式2);
? ? ? ? ? 表達(dá)式1:初始化循環(huán)控制變量;
? ? ? ? ? 表達(dá)式2:作為循環(huán)判斷條件颠悬;
? ? ? ? ? 表達(dá)式3:循環(huán)變量的改變;
循環(huán)嵌套:在一個(gè)循環(huán)語句又包含另一個(gè)循環(huán)語句矮燎。
continue用于循環(huán)體內(nèi)部,作用是結(jié)束本次循環(huán)赔癌,開始執(zhí)行新的循環(huán)诞外。
break跳出循環(huán),不在執(zhí)行新的循環(huán)灾票,只跳出break所在這一層循環(huán)峡谊。
return :直接跳出循環(huán),并且不再執(zhí)行新的循環(huán)。
第四章
一維數(shù)組概念:具有相同數(shù)據(jù)類型的一組變量的集合既们;
特點(diǎn):數(shù)組中可以存儲相同類型的多個(gè)變量濒析;
注意問題:
1)數(shù)組元素的內(nèi)存浪費(fèi)
2)越界訪問;
二維數(shù)組格式:類型說明符 數(shù)組名[常量表達(dá)式1][常量表達(dá)式2]. ?int a[2][3];
引用形式:數(shù)組名 [下標(biāo)][下標(biāo)]啥纸。
第五章
理解為什么要使用函數(shù)悼枢?(好處)
1)可以更好的組合代碼;
2)可以多人合作開發(fā)脾拆;
3)有利于早發(fā)現(xiàn)問題
函數(shù)邏輯馒索?輸入+執(zhí)行+輸出
函數(shù)定義: 函數(shù)頭+函數(shù)體
? 返回值類型 函數(shù)名(函數(shù)的形參列表)
? {
? ? ? 函數(shù)執(zhí)行體語句
? }
函數(shù)名的使用;
? a名船、聲明函數(shù)绰上;編譯階段
? b、函數(shù)的實(shí)現(xiàn):執(zhí)行階段渠驼,實(shí)現(xiàn)對函數(shù)的具體功能
? c蜈块、使用函數(shù):函數(shù)的調(diào)用(傳參)
C語言中函數(shù)的傳參:傳值、傳地址(傳指針)
? 傳值的原理:主調(diào)函數(shù)迷扇、被調(diào)函數(shù)百揭、形式參數(shù)、實(shí)際參數(shù)
? ? ? ?1) 傳值方式蜓席,在函數(shù)調(diào)用時(shí)器一,主調(diào)函數(shù)把實(shí)參變量的值拷貝一份,賦值給被調(diào)函數(shù)的形參變量
? ? ? 2) 在被調(diào)函數(shù)體內(nèi)厨内,操作和修改的是形參的值祈秕,實(shí)參不受影響
? ? ? 3) 只是單向傳遞,從實(shí)參到形參
函數(shù)的嵌套(調(diào)用的嵌套)
遞歸函數(shù)(特殊的嵌套函數(shù))
? 原理:取代了循環(huán)
? 注意:(死循環(huán))
變量與函數(shù)之間的關(guān)系:
? 左值:可做右值
? 右值:不可做左值
? ?分類:全局變量與局部變量(作用域范圍雏胃、生命周期)
? static修飾的變量:全局變量與局部變量(作用域范圍请毛、生命周期)
? 函數(shù):全局函數(shù)與static函數(shù)(作用域范圍、生命周期)
? 外部文件中全局變量與全局函數(shù)的使用:extern關(guān)鍵字修飾
靜態(tài)局部變量
(1)未經(jīng)初始化時(shí)系統(tǒng)默認(rèn)初始化為0瞭亮;
(2)生命周期:編譯——程序結(jié)束
(3)可以保留上一次執(zhí)行后變量的值
全局變量和局部變量在程序中的生存期和作用域?qū)Ρ龋?/b>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 生存期? ? ? ? ? ? ? ? 作用域
普通全局變量? ? ? 整個(gè)程序? ? ? ? ? ? 整個(gè)程序
static全局? ? ? ? 整個(gè)程序? ? ? ? ? ? 只能用于本文件內(nèi)部
普通局部變量? ? ? 函數(shù)域? ? ? ? ? ? ? 函數(shù)域或程序塊
static局部? ? ? 整個(gè)程序? ? ? ? ? ? 函數(shù)域或程序塊
第六章指針
? a方仿、指針類型與地址的理解?
? b统翩、指針數(shù)據(jù)類型的理解
? c仙蚜、指針變量的理解?特點(diǎn)
? d唆缴、指針變量的賦值與訪問操作鳍征?
指針變量的聲明方式(三種),每種寫法的意義
指針初始化問題面徽?
? 面試考題:野指針與空指針的區(qū)別
指針作為函數(shù)的參數(shù):原理艳丛?解決的問題匣掸?
指針作為函數(shù)的返回值類型?
? 面試考題:為什么不能返回一個(gè)局部變量的地址(局部變量的指針)
內(nèi)存分配問題的理解
? 面試考題:
? 1氮双、變量在內(nèi)存中的分配存儲區(qū)域(5大區(qū))各自的特點(diǎn)
? 2碰酝、變量的存儲類型分為兩種情況:
? ? ? 第一種:按照空間的角度(作用域范圍)分為:全局變量存儲和局部變量存儲?
? ? ? 第二種:按照時(shí)間的角度(生命周期)分為:靜態(tài)存儲方式和動(dòng)態(tài)存儲方式戴差?
? ? ? ? ? ? 堆區(qū)與棧區(qū)的存儲區(qū)別送爸?
? 3、堆區(qū)內(nèi)存管理函數(shù)的使用:
? ? ? malloc暖释、calloc袭厂、realloc、free的作用以及應(yīng)用?
二維指針的理解:
多維指針球匕;
指針和數(shù)組:重點(diǎn):數(shù)組的名字就是一個(gè)指向數(shù)組首元素的指針
指針數(shù)組:數(shù)組里每個(gè)元素內(nèi)部存放的是地址編號
數(shù)組指針:一個(gè)指針纹磺,指向數(shù)組整體;
指針的運(yùn)算可以-亮曹,不可以+
參數(shù)傳遞:
傳指針橄杨,通過對其形參的間接改變,改變實(shí)參的值
指針與const的關(guān)系
指針加const指針不能改變指向
int * const p
const int * p
函數(shù)指針:
指向函數(shù)的指針包含了函數(shù)的地址照卦,可以通過它來調(diào)用函數(shù)
格式:類型說明符 (*函數(shù)名)(參數(shù))
確定一個(gè)函數(shù)指針的類型就是指針指向的函數(shù)的參數(shù)類型和返回值類型
第七章 字符串
字符串:用雙引號包圍式矫;結(jié)束標(biāo)志‘\0’
字符數(shù)組:數(shù)組每個(gè)元素都是字符,字符用單引號包圍役耕。
字符數(shù)組初始化方式? 兩種
可變字符串:
可以把一個(gè)字符串賦值給一個(gè)char*類型的指針采转,但是不能通過指針來修改這個(gè)字符串。
常用的字符串操作函數(shù)
strlen
原型:unsigned long strlen(const char* s)
返回字符串的字符數(shù)長度蹄葱,有效長度
strcpy
原型:char* strcpy(char * to,const char* from)
拷貝一個(gè)字符串氏义;
to必須指向有效的足夠大的可操作的存儲空間
from的內(nèi)容在內(nèi)存上粘的存儲空間必須小于等于to所指定的存儲空間
strcat
字符串鏈接函數(shù)锄列;
strcmp
原型:int strcmp(const char *str1,const char* str2)
字符串比較函數(shù)图云;
4、字符串?dāng)?shù)組
1邻邮、字符串?dāng)?shù)組的理解:
字符串?dāng)?shù)組存儲的竣况,不是每一個(gè)字符串的內(nèi)容,而是各個(gè)字符串首地址的指針筒严。其定義形式如下所示有三種:
(1)特點(diǎn):該字符串?dāng)?shù)組中的內(nèi)容可以被修改
char str1[]="hello";
char str2[]="world";
char str3[]="!";
char * array[]={str1,str2,str3};
int i;//遍歷訪問
for(i=0;i<3;i++)
{
printf("%s\n",array[i]);
}
(2)特點(diǎn):該字符串?dāng)?shù)組中的內(nèi)容不可以被修改(通過指針來訪問常量字符串)
char * str1="hello";
char * str2="world";
char * str3="!";
char * array[]={str1,str2,str3};
(3)
特點(diǎn):該字符串?dāng)?shù)組中的內(nèi)容不可以被修改(通過指針來訪問常量字符串)
char * array[]={"hello","world","!"};
2丹泉、字符串?dāng)?shù)組名可以被看作是一個(gè)指向字符型指針的二維指針。
字符串?dāng)?shù)組的理解(二級指針+二維數(shù)組)
5鸭蛙、文件操作
1摹恨、打開文件;
函數(shù)原型:
FILE*fopen(const char * filename,const char * openstyle)
(1)娶视、第一個(gè)參數(shù)為要打開的文件名字
(2)晒哄、第二個(gè)參數(shù)為打開文件的方式
(3)睁宰、返回值類型為FILE* FILE是一個(gè)結(jié)構(gòu)體(關(guān)于文件信息的數(shù)據(jù)包)
(4)、當(dāng)打開文件失敗時(shí)返回空指針NULL
打開方式:
r:可讀寝凌,該文件必須存在
w:可寫柒傻,先將文件長度截為0,如果文件不存在先創(chuàng)建
a:可寫较木,向已有文件尾追加內(nèi)容红符,不存在先創(chuàng)建
r+:可讀可寫
w+:可讀可寫
a+:可讀可寫
注意:使用任意一種“w”模式打開已有文件,文件內(nèi)容將會被刪除伐债,以便程序以一個(gè)空文件開始操作
2预侯、關(guān)閉文件
函數(shù)原型:
int fcolse(FILE*)
(1)參數(shù)為文件指針
(2)返回值 如果關(guān)閉成功返回0;否返回EOF
標(biāo)準(zhǔn)輸入? ? ? stdin? 鍵盤
標(biāo)準(zhǔn)輸出? ? ? stdout? 顯示器
標(biāo)準(zhǔn)錯(cuò)誤? ? ? stderr? 顯示器
重要
(1)printf:是把格式字符串輸出到標(biāo)準(zhǔn)輸出
(2)sprintf:是把格式字符串輸出到指定字符串中峰锁,所以參數(shù)比printf多一個(gè)char*雌桑。那就是目標(biāo)字符串地址
(3)fprintf:是把格式字符串輸出到指定的文件設(shè)備中,所以參數(shù)比printf多一個(gè)文件指針FILE*
(1)scnaf:從控制臺輸入
(2)fscanf:從文件輸入
(3)sscanf:從指定字符串輸入
第八章:枚舉祖今、結(jié)構(gòu)體校坑、聯(lián)合體
1、枚舉類型
概念:c語言的枚舉類型實(shí)質(zhì)就是整形變量千诬,只不過通過枚舉類型將一類有關(guān)聯(lián)的標(biāo)識組合起來耍目。
特點(diǎn):增強(qiáng)程序的可讀性和可維護(hù)性。
enum OS{iOS=1,Android=2,Wphone=3,Other=4};
enum weekday{mon,tue,wed,thr,fri,sat,sun} a ,b,c;
weekday為枚舉類型名徐绑,a,b,c為枚舉變量名邪驮。
(1)枚舉類型的取值范圍,是整數(shù)取值范圍的一個(gè)子集傲茄。
(2)每個(gè)值對應(yīng)一個(gè)整數(shù)毅访,默認(rèn)從0開始,依次加一盘榨。
枚舉聲明變量的方式喻粹;
(1)enum weekday
{
…….
};
enum weekday a,b,c;//a的數(shù)據(jù)類型就是enum weekday
(2)enum weekday
{
…….
}a,b,c;//定義類型的同時(shí)聲明變量
(3)enum
{
……
}a,b,c;//定義類型同時(shí)聲明變量,一般很少用
枚舉類型的作用
(1)可以代替整形的宏定義草巡,增強(qiáng)代碼的可維護(hù)性守呜。
(2)可用在switch語句中,作為常量使用山憨。
(3)使用枚舉變量時(shí)查乒,應(yīng)該把枚舉變量的值賦值為枚舉中常量中某個(gè)常量的值。
(4)c幫你縫裝好一個(gè)define 集合郁竟,用便于記憶的字符來代表常量玛迄。
2、結(jié)構(gòu)體類型
關(guān)鍵字:struct
概念:用來定義結(jié)構(gòu)體的關(guān)鍵字棚亩。
作用:用已有類型的集合蓖议,定義一個(gè)新類型
struct
{
char fname[8];
char sname[16];
char exam[16];
char grade;
}record;//結(jié)構(gòu)變量
定義結(jié)構(gòu)體的形式
(1)直接定義結(jié)構(gòu)體變量藻肄,結(jié)構(gòu)體本身沒有名字。
(2)用結(jié)構(gòu)體類型名拒担,聲明一個(gè)結(jié)構(gòu)體變量
(3)用typedef直接給沒有結(jié)構(gòu)體類型名的結(jié)構(gòu)體類型嘹屯,起一個(gè)別名。
4 从撼、結(jié)構(gòu)體訪問
4州弟、2指向結(jié)構(gòu)體的指針
該結(jié)構(gòu)體指針指向結(jié)構(gòu)體的第一個(gè)成員地址,相當(dāng)于一個(gè)多維指針
5低零、結(jié)構(gòu)體賦值
(1)婆翔、<string.h>提供的內(nèi)存拷貝函數(shù)
void * memcpy(void * dest,const void *src,size_t n);
功能:從源src所指的內(nèi)存地址的起始位置開始拷貝n個(gè)字節(jié)到目標(biāo) dest所指的內(nèi)存地址的起始位置中。
返回值:函數(shù)返回指向dest的指針掏婶。
總結(jié):把一個(gè)結(jié)構(gòu)體每個(gè)成員的值啃奴,拷貝給另一個(gè)結(jié)構(gòu)體中對應(yīng)的成員。
實(shí)例中:memcpy(&sam2,&sam1,sizeof(SAMPLE));
strcpy與memcpy的區(qū)別:
(1)復(fù)制的內(nèi)容不同雄妥。strcpy只復(fù)制字符串最蕾,而memcpy可以復(fù)制任意內(nèi)容,
例如字符數(shù)組老厌、整型瘟则、結(jié)構(gòu)體、類等枝秤。
(2)復(fù)制的方法不同醋拧。strcpy不需要指定長度,它遇到被復(fù)制字符的串結(jié)束符‘\0’才結(jié)束淀弹,所以容易造成內(nèi)容溢出丹壕。memcpy則是根據(jù)其第3個(gè)參數(shù)決定復(fù)制的長度。
(3)用途不同薇溃。通常在復(fù)制字符串時(shí)用strcpy菌赖,而需要復(fù)制其他類型數(shù)據(jù)時(shí)則一般用memcpy。
6痊焊、結(jié)構(gòu)體大小與內(nèi)存對齊
每個(gè)特定平臺上的編譯器都有自己的默認(rèn)“對齊系數(shù)”(也叫對齊模數(shù))程序員可以通過
#pragma pack(n)其中n是“對齊系數(shù)”
內(nèi)存分配法
數(shù)據(jù)對齊:是指數(shù)據(jù)所在的內(nèi)存地址必須是該數(shù)據(jù)長度的整數(shù)倍
結(jié)構(gòu)體的長度一定是最長的數(shù)據(jù)元素的整數(shù)倍
2盏袄、偏移量計(jì)算法
偏移量指的是結(jié)構(gòu)體變量中成員的地址和結(jié)構(gòu)體變量地址的差。結(jié)構(gòu)體大小等于最后一個(gè)成員的偏移量加上最后一個(gè)成員的大小薄啥。顯然,結(jié)構(gòu)體變量中的第一個(gè)成員的地址就是結(jié)構(gòu)體變量的首地址逛尚,因此垄惧,第一個(gè)成員的偏移量基本都為0。
編譯器在編譯程序時(shí)的原則
(1)結(jié)構(gòu)體變量中成員的偏移量必須是成員大小的整數(shù)倍(0被認(rèn)為是任何數(shù)的整數(shù)倍)
(2)結(jié)構(gòu)體大小必須是所有成員大小的整數(shù)倍
總結(jié):在設(shè)計(jì)結(jié)構(gòu)體的時(shí)候绰寞,一般會遵照一個(gè)習(xí)慣到逊,就是把占用空間小的類型排在前面铣口,占用空間大的類型排在后面,這樣可以相對節(jié)約一些對齊空間觉壶。
7脑题、聯(lián)合體
(1)聯(lián)合體是一個(gè)結(jié)構(gòu)
(2)他的所有成員相對于基地址的偏移量都為0
(3)此結(jié)構(gòu)空間要大到足夠容納最“寬的成員”
(4)其對齊方式要適合其中所有的成員
定義聯(lián)合體類型變量的一般形式
union 聯(lián)合體名
{
成員列表;
變量表列铜靶;
}
聯(lián)合體所占的內(nèi)存長度等于最長的成員的長度
大端法:高位字節(jié)排放在內(nèi)存低地址端叔遂,低位字節(jié)排放在內(nèi)存高地址端
小端法:低位字節(jié)排放在內(nèi)存低地址端,高位字節(jié)排放在內(nèi)存高地址端
第九章預(yù)處理及程序執(zhí)行過程/Users/admin/Downloads/軟件執(zhí)行過程.png
預(yù)處理:在編譯之前争剿,系統(tǒng)對源文件提前進(jìn)行的內(nèi)存處理已艰。
指令? ? ? ? ? ? ? ? ? 用途
#? ? ? ? ? ? ? 空指令,無任何效果
#include? ? ? 包含一個(gè)源代碼文件
#define? ? ? ? 定義宏
#undef? ? ? ? 取消已定義的宏
#if? ? ? ? ? ? 如果給定條件為真蚕苇,則編譯下面代碼
#ifdef? ? ? ? 如果宏已經(jīng)定義哩掺,則編譯下面代碼
#ifndef? ? ? ? 如果宏沒有定義,則編譯下面代碼
#elif? ? ? ? ? 如果前面的#if給定條件不為真涩笤,當(dāng)前條件為真嚼吞,則編譯下面代碼,相當(dāng)于#elseif
#endif? ? ? ? 結(jié)束一個(gè)#if.....#else...條件編譯塊
#error? ? ? ? 指令將使編譯器顯示一條錯(cuò)誤信息蹬碧,然后停止編譯
#line? ? ? ? ? 指令可以改變編譯器用來指出警告和錯(cuò)誤信息的文件號和行號
#pragma? ? ? ? 指令沒有正式的定義誊薄,編譯器可以自定義其用途,典型的用法是禁止或允許某些煩人的警告信息
第九章 ? ? 預(yù)處理及程序執(zhí)行過程
1锰茉、頭文件包含
在編譯之前呢蔫,把頭文件的內(nèi)容,整個(gè)拷貝到當(dāng)前源文件里飒筑。之后再進(jìn)行編譯片吊。
#include<stdio.h>告訴預(yù)處理程序在編譯器自帶的或外部庫的頭文件中搜索被包含的頭文件
#include”stdio.h”告訴預(yù)處理程序在當(dāng)前被編譯的應(yīng)用程序的源代碼文件中搜索被包含的頭文件,如果找不到协屡,在搜索編譯器自帶的頭文件俏脊。
2、宏替換
宏:是一種批量批處理上的稱謂肤晓。宏是一種規(guī)則或模式爷贫,或稱語法替換,用于說明某一特定輸入(通常是字符串)如何根據(jù)定義的規(guī)則轉(zhuǎn)換成對應(yīng)的輸出(通常也是字符串)补憾。宏定義可以幫助我們防止出錯(cuò)漫萄,提高代碼的可移植性和可讀性。
語法:#define宏的名字(最好都用大寫字母)宏將被替換的內(nèi)容
2盈匾、2宏展開
宏展開也稱宏替換腾务,原理:在編譯之前把宏的名字替換成真實(shí)的內(nèi)容,宏————————只是作代碼替換來用削饵。這種替換在預(yù)編譯是進(jìn)行岩瘦,稱作宏展開未巫。
例如:
#define PI 3.14
宏是文本,在替換時(shí)不會進(jìn)行計(jì)算
面試題:提高了程序的運(yùn)行效果減小運(yùn)行時(shí)間启昧,但是增大了我們對程序代碼的擴(kuò)展叙凡,
替換函數(shù):
首先,寫成宏定義
#define MAX(a,b)((a)>(b)?(a):(b))
其次密末,用函數(shù)實(shí)現(xiàn)
int max(int a,int b)
{
return (a>b a:b);
}
首先握爷,函數(shù)調(diào)用會帶來額外的開銷,它需要開辟一片椝找#空間饼拍,記錄返回地址,將形參壓棧田炭,從函數(shù)返回還要釋放堆棧师抄。會降低代碼效率,代碼量也會大大增加教硫。
其次叨吮,函數(shù)的參數(shù)必須被聲明為一種特定的類型,所以它只能在類型合適的表達(dá)式上使用瞬矩,我們?nèi)绻容^兩個(gè)浮點(diǎn)型的大小茶鉴,就不得不在寫一個(gè)專門針對浮點(diǎn)型的比較函數(shù)。而宏是與類型無關(guān)的景用。
注意:替換函數(shù)時(shí)宏替換的參數(shù)都要加上括號
#define MAX(A,B) ((A)>(B)? (A):(B))//OK
#define MAX(A,B) (A>B? A:B)//ERROR
總結(jié):當(dāng)用宏去定義函數(shù)時(shí)涵叮,宏被替換的內(nèi)容中的參數(shù)都需要加上括號()
2、3宏函數(shù)
替換自定義函數(shù)(除了最后大括號的結(jié)束行伞插,其余都要加上“\”)
思考割粮;有些任務(wù)根本無法用函數(shù)實(shí)現(xiàn),但是用宏定義卻很好實(shí)現(xiàn)媚污,比如參數(shù)類型沒法做為參數(shù)傳遞給函數(shù)舀瓢,但是可以把參數(shù)類型傳遞給帶參的宏。
3耗美、條件包含
條件包含也稱為“條件編譯指令”或“條件預(yù)編譯”京髓。? ? ? ?
4、程序執(zhí)行過程
程序編譯執(zhí)行過程基本流為:預(yù)處理商架、編譯堰怨、匯編、鏈接甸私、運(yùn)行诚些。
第一:預(yù)處理
gcc -E hello.c-o hello.i
預(yù)處理后的.i文件不包含任何宏定義
第二:編譯
gcc -S hello.i-o hello.s
編譯之后生成.s文件,存儲的為匯編代碼
第三:匯編
gcc? -c hello.s -o hello.o
此時(shí)存儲的為二進(jìn)制數(shù)據(jù)
第四:鏈接
每個(gè).c文件經(jīng)過上述步驟都生成了對應(yīng)的目標(biāo)文件(擴(kuò)展名為.o或.obj)把生成的所有目標(biāo)文件組裝到一起的過程就是連接皇型。