指針
指針是一個(gè)變量,其值為地址衅疙,聲明或不再使用后都要將其置為0(類似java釋放對象后置為NULL)莲趣。
野指針
產(chǎn)生原因->
(定義時(shí)未初始化)不初始化會隨機(jī)指向隨機(jī)區(qū)域,因?yàn)槿魏沃羔樧兞浚ǔ藄tatic修飾的指針變量)在定義的時(shí)候是不會默認(rèn)固定值的炼蛤,他的默認(rèn)值是隨機(jī)的妖爷。
(釋放時(shí)未被置NULL(懸空指針))使用molloc開辟內(nèi)存空間時(shí),要檢查返回值是否為NULL,如為NULL則開辟失敗絮识,如不為NULL則指針指向的時(shí)開辟內(nèi)存空間的首地址绿聘。指針指向的內(nèi)存空間在用free()或delet(delet是一個(gè)操作符)釋放后如果沒有置null或賦其他值也會成為野指針。
(指向棧內(nèi)存的指針)棧內(nèi)存在函數(shù)執(zhí)行完畢之后會釋放
危害->
指針指向一個(gè)隨機(jī)地址次舌,不受程序控制熄攘。如指向已經(jīng)被刪除的對象或指向一塊沒有訪問權(quán)限的內(nèi)存。指針再次被使用時(shí)彼念,導(dǎo)致程序異常挪圾。
如何規(guī)避->
初始化時(shí)置為NULL,指針使用完時(shí)一定要釋放并置為NULL逐沙,良好的編程習(xí)慣
指針聲明
int *p=NULL哲思;比較好看的寫法
int* p=NULL;個(gè)人認(rèn)為這個(gè)寫法比較好理解
int * p=NULL吩案; 也可以這么寫不會報(bào)錯(cuò)
int* a,b棚赔;這么寫沒有初始化,必須初始化
指針使用
int i=10徘郭;聲明一個(gè)int類型的變量i賦值為10靠益;
int* p=NULL;聲明一個(gè)int類型指針p初始化NULL残揉;
p=&i胧后;使用取地址符&將i的地址賦值給指針p;(十六進(jìn)制打印printf("%#x\n",&i)抱环,printf("%#x\n",p)得出結(jié)果是一樣的)
解引用:解析并返回內(nèi)存地址中的值?
int i2=*p壳快;(printf("%d\n", i2);的結(jié)果為10)
*p=100;(printf("%d\n", i);的結(jié)果為100江醇,因?yàn)閜是指向i的地址*p=100相當(dāng)于往i的地址的內(nèi)存保存100)
指針運(yùn)算
int i1[] = {11,22,33,44,55};? // 聲明一個(gè)int類型數(shù)組 (java中可以寫成 int[] i1={})
int* p1 = i1;//數(shù)組名就是數(shù)組在內(nèi)存中的首地址濒憋,數(shù)組是內(nèi)存連續(xù)存儲的 解引用*數(shù)組名會得到第一個(gè)元素,i1==&i1;i1+1!=&i1+1
for (size_t i =0; i <5; ++i) {
printf("%d\n", *p1++);// (++優(yōu)先級高陶夜,p1++之后取值,地址改變之后取值)輸出 11裆站,22条辟,33,44宏胯,55? 地址++
printf("%d\n", ++*p1);//++*不成立羽嫡,++(*p1)(個(gè)人理解)輸出 12 13 14 15 16 值++
}
數(shù)組指針與指針數(shù)組
int (*array3)[2] = &array;//數(shù)組指針 與int *p=&i;一樣肩袍,指針p是存著i的地址杭棵,指針array3存著array的地址,一個(gè)是int數(shù)組類型指針,一個(gè)是int類型指針。
int* array2[2] = {11,22};//指針數(shù)組魂爪,array2數(shù)組被賦值{11先舷,22}但是array2中第一個(gè)元素是一個(gè)指向11的指針,第二個(gè)是指向22的指針滓侍,數(shù)組中的元素類型是int類型的指針蒋川,所以叫指針數(shù)組
int array2[2]={11,22};int數(shù)組,元素值就是int類型的11和22
二維數(shù)組指針??int aa[2][3] = {{11, 22, 33},{44, 55, 66}};或?int aa[2][3] = {11, 22, 33, 44, 55, 66};int (*arr1)[3] = &aa;arr1取值*(*arr1+0)撩笆,*(*arr1+1)捺球,也可以arr1[x][y]下標(biāo)的方法取值。
指針常量與常量指針
從左往右讀? ? const再*之前就是常量指針夕冲,反之指針常量氮兵,常量指針可修改指向,不可修改指向的值歹鱼,指針常量可修改指向的值泣栈,不可修改指向
多級指針
指向指針的指針,一個(gè)指針包含另一個(gè)指向值的指針的地址醉冤。
指針占用空間
指針地址在64位計(jì)算機(jī)中sizeof(p)=8秩霍,32位sizeof(p)=4
函數(shù)
與java的方法沒有區(qū)別,都是一組執(zhí)行一個(gè)任務(wù)的語句蚁阳,也都有函數(shù)頭和函數(shù)體構(gòu)成铃绒。函數(shù)需聲明在使用之前。傳值調(diào)用不會影響實(shí)參螺捐,引用調(diào)用可以修改實(shí)參颠悬。
可變參數(shù)
函數(shù)指針
函數(shù)指針是指向函數(shù)的指針變量
寫法:函數(shù)返回值(*函數(shù)指針變量)(函數(shù)的參數(shù)) ——》void(*p)(int)
預(yù)處理器
預(yù)處理器不是編譯器,但是他是編譯過程中一個(gè)單獨(dú)的步驟定血,預(yù)處理器是一個(gè)文本替換工具赔癌,所有的預(yù)處理其都是以井號(#)開頭
常用的預(yù)處理器
宏
宏就是文本替換,#define A 1澜沟,宏一般使用大寫區(qū)分灾票,在代碼中使用A就會被替換成1。
宏函數(shù)#define test(a, b) a>b?a:b
#define apend(arg,arg2) arg ## arg2? ?##拼接符
宏定義一行不夠使用? \? 延續(xù)符也叫宏換行符
可變宏:#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"NDK", __VA_ARGS__);
#define MULTI(x,y) x*y這有個(gè)坑?printf("%d\n", MULTI(2, 2));輸出4??printf("%d\n", MULTI(1+1, 2)); =》1+1*2=3