C語(yǔ)言指針
指針
*的兩種含義:
1.?在定義時(shí)表示 后面的變量是指針
2.?使用時(shí)表示取值(取指針地址的值)
不論指向的類(lèi)型是什么,指針大小為4字節(jié)(64位為8字節(jié) )
?
下列交換a b值的程序?yàn)槭裁村e(cuò)誤?
原因是只交換了形參xy的值,在執(zhí)行swap()函數(shù)后釋放xy。
沒(méi)有交換實(shí)參
如果要交換實(shí)參的值,必須要傳地址
修改如下:
*x就是a , *y就是b。
野指針
int *p; ???//不能隨意定義指針
如何合法使用內(nèi)存?
1 系統(tǒng)分配
????Int a ;
????Int ?*p=&a;
2?用戶(hù)申請(qǐng)內(nèi)存(堆內(nèi)存)
????malloc(32);//動(dòng)態(tài)內(nèi)存分配,運(yùn)行時(shí)才能找到一個(gè)內(nèi)存使用
????malloc()不清楚什么類(lèi)型的返回值,所以干脆返回void類(lèi)型
在申請(qǐng)內(nèi)存時(shí)需要強(qiáng)制轉(zhuǎn)換類(lèi)型,如下:
????char ?*str=(char *)malloc(32); ?//str指針指向了申請(qǐng)的32位內(nèi)存
?????free(str);//用完內(nèi)存后需要釋放內(nèi)存
?????str=NULL;//防止野指針
指針和數(shù)組
指針數(shù)組是數(shù)組,
數(shù)組指針是指針,如 int (*p)[5]; ?一個(gè)指針占4個(gè)字節(jié)。

數(shù)組名為首元素的地址:
int *p = a;??和???int *p = &a[0];?????相同
a[i] ?和??*(p+i)?????相同
一維數(shù)組a[10],a表示首元素地址;
二維數(shù)組a[3][4],a表示首行地址(16字節(jié)),a[0]表示首行首元素地址(4字節(jié))。
&a表示數(shù)組地址(48字節(jié),12*4).
?
/*
問(wèn):如何不用3,4,直接用函數(shù)表示幾行幾列?
*/
/*
問(wèn):char str = "hello world";和 char *p = "hello world"; 區(qū)別?
?

//str++ ??報(bào)錯(cuò) ??數(shù)組名是常指針(地址常量),不能修改
//p++ ??????????指向下一個(gè)元素e
//str[0] = ‘x’; ??????????把str首元素改為x
//p[0] = ‘x’; 不能運(yùn)行 ??字符串常量,不能被修改
//sizeof(str) = 5*4(字節(jié)長(zhǎng)度) ?32位操作系統(tǒng)
//sizeof(p) = ?4
*/
/*
問(wèn):P1[0],p2[0],p3[0]的值分別是多少?
int ?a[5] = {1,2,3,4,5}; //設(shè)a的首地址為0x100
1.int *p1 = (int*)(&a + 1);
2.int *p2 = (int*)((int)a+1);
3.int *p3 = (int*)(a + 1);??
1.&a表示數(shù)組的地址 ????a表示數(shù)組首元素地址
&a+1 ?表示跳過(guò)20字節(jié),直接跳到下個(gè)數(shù)組;將數(shù)組指針轉(zhuǎn)為(int*)型,指向下一個(gè)數(shù)組的首地址,由于下個(gè)數(shù)組沒(méi)有定義,所以
P1[0]為野指針
?
2.P[2]先執(zhí)行(int*)((int)a+1);,
將a的首地址0x100轉(zhuǎn)為int型100,加一得101,再轉(zhuǎn)為(int*)型0x101 進(jìn)入a[0]的首地址的第二個(gè)字節(jié)。
P2[0]不合法
?
3.P3[0]為2, 就算不轉(zhuǎn) (a+1)也為(int*)類(lèi)型
*/
指針和字符串?
char *string[] = {"hello","world"};
printf("%s\n",string);
?
string是數(shù)組還是指針?(64位)
????先括號(hào),再char*,是數(shù)組,存放的內(nèi)容為指針,指針型數(shù)組。
?
printf("%s\n",string); 能不能輸出hello world?
????string表示數(shù)組首元素地址,不能輸出(野指針)
????printf("%s\n",string[0]); 輸出hello
????printf("%s\n",string[1]); 輸出world?
函數(shù)指針
指向函數(shù)的指針
????函數(shù)名為該函數(shù)所占內(nèi)存區(qū)的首地址 ??函數(shù)名 = 函數(shù)內(nèi)存首地址(函數(shù)入口地址)
????把函數(shù)的首地址(函數(shù)入口地址)賦予一個(gè)指針變量,使指針指向函數(shù)。
????通過(guò)指針變量就可以找到調(diào)用這個(gè)函數(shù),這種指向函數(shù)的指針叫“函數(shù)指針變量”
格式為:類(lèi)型說(shuō)明符(*指針變量名)();
如: ??void (*p)(); ????*p表示它是一個(gè)指針,右邊的括號(hào)表示它指向一個(gè)函數(shù) ,括號(hào)里空的表明它沒(méi)有參數(shù) ,void表示它沒(méi)有返回值 ???????
?
申明很麻煩,可以加一個(gè)定義 typedef ?int(*T)(int,int); ?這樣T就是定義函數(shù)指針了
T ?q = add; 等價(jià)于 int(*q)(int,int);
指針函數(shù)
返回值是指針的函數(shù)
/*
int (*p)() ?????和 ????int *p()????的區(qū)別?
????int (*p)() 是一個(gè)函數(shù)指針,是一個(gè)變量,返回值是整形。
????int *p() 是一個(gè)函數(shù)聲明,說(shuō)明p是一個(gè)指針型函數(shù),返回值是一個(gè)指向整形量的指針。
????找到變量名,先右后左
*/
????????????????????????????????????????回調(diào)函數(shù)
回調(diào)函數(shù):把函數(shù)名作為另一個(gè)函數(shù)的參數(shù)
作用:修改函數(shù)的功能
冒泡排序
????程序?qū)崿F(xiàn)了從小到大排序,在函數(shù)都封裝好之后,要實(shí)現(xiàn)從大到小排序,如何實(shí)現(xiàn)?
能不能讓paixu()既實(shí)現(xiàn)從小到大排序又實(shí)現(xiàn)從大到小排序?????????????????????????????????????????????????????? ? ??????????????????????????????????????????????????????
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????
復(fù)雜函數(shù)聲明
1.int*(*(*fp)(int))[10];
2.int*(*(*array[5])())();
怎么解釋?zhuān)?/p>
右左法則
1.?int*(*(*fp)(int))[10];
先找變量fp, 看括號(hào) ?????????int*(*(*fp)(int))[10]; ??,fp是一個(gè)指針
向右看,也是一個(gè)括號(hào) (int), ??int*(*(*fp)(int))[10];
括號(hào)表明指針指向一個(gè)函數(shù),有整型的參數(shù)。
向左看,函數(shù)的返回值 ???????int*(*(*fp)(int))[10]; ?返回值是一個(gè)指針
得出fp是一個(gè)指針指向函數(shù),函數(shù)有一個(gè)int類(lèi)型的參數(shù),函數(shù)的返回值也是指針。
?
再向右看,返回的指針指向[10],int*(*(*fp)(int))[10]; ?,指向一個(gè)10個(gè)元素的數(shù)組。
再向左看,10個(gè)元素的類(lèi)型,int*(*(*fp)(int))[10]; , 每個(gè)元素都是整形指針。
?
總結(jié):fp是指針,指向一個(gè)函數(shù),函數(shù)有整型參數(shù),函數(shù)的返回值是指針,指向有10個(gè)元素的數(shù)組,元素是整型指針。
?
2.?int*(*(*array[5])())();
array是一個(gè)有5個(gè)元素的數(shù)組,元素是指針,指向一個(gè)函數(shù),函數(shù)沒(méi)有參數(shù),函數(shù)的返回值是指針,指針指向另一個(gè)
函數(shù),這個(gè)函數(shù)沒(méi)有參數(shù),返回值是一個(gè)整型指針。
問(wèn):const和volatile能同時(shí)使用嗎?
可以,volatile表示編譯器不要優(yōu)化變量;
const修飾指針時(shí),表示不能使用指針來(lái)修改地址上的值,但是可以用其他指針或變量修改。
const修飾變量時(shí),表示不能使用變量直接修改值,但是可以使用其他指針來(lái)修改。