前沿:
創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),丹江口企業(yè)網(wǎng)站建設(shè),丹江口品牌網(wǎng)站建設(shè),網(wǎng)站定制,丹江口網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,丹江口網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。有人曾說過不會指針等于沒有學(xué)習(xí)c語言,而我也是非常認(rèn)同這個(gè)觀點(diǎn)的,要想學(xué)習(xí)好c語言,指針是比不可缺少的,如果指針學(xué)不會c語言也就沒辦法學(xué)好,而向如此越重要的東西越比較難學(xué),但難學(xué)并不代表學(xué)不會,這片文章將由簡單到復(fù)雜讓你深刻的了解指針,從此不再害怕指針的學(xué)習(xí)。
思維導(dǎo)圖:
目錄
一、指針的初步認(rèn)識:
1.1指針是什么:
1.2指針的類型:
1.3指針的大?。?/p>
1.4指針的定義和使用:
1.5野指針:
二、指針的進(jìn)階認(rèn)識:
2.1字符指針:
2.2指針數(shù)組:
2.3數(shù)組指針:
2.4函數(shù)指針:
2.5函數(shù)指針數(shù)組:
總結(jié):
1.1.1? 學(xué)習(xí)一個(gè)知識我們需要了解他的本質(zhì),正如我們學(xué)習(xí)指針,我們要先了解他是什么,從生活中舉例,指針就好比我們家的門牌號一樣,每個(gè)房間都有自己的門牌號,而我們則可以通過門牌號找到我們想要找到的人,別人也可以通過門牌號找到你。為此我們可以初步的了解指針就表示地址,通過指針我們可以找到相應(yīng)類型的變量。所以我們平常口語中的指針其實(shí)就是指針變量,是用來存放內(nèi)存地址的變量。
1.1.2 這樣我們就好理解一個(gè)變量所占的內(nèi)存叫做字節(jié),而地址指向的就是所占字節(jié)的位置也就是地址。
這里的0xFFFFFFFFF則就表示地址。
1.2指針的類型:?1.2.1 像int double float char 類型一樣指針也有自己相應(yīng)的類型,而指針的類型就是指針?biāo)赶蛟厥鞘裁搭愋?,指向int的指針就是整型指針,指向char類型的就是字符型指針等等。
#includeint main()
{
int a;
int *ra=&a;
char b;
char* rb=&b; //等等
return 0;
}
1.3指針的大小:1.3.1指針的大小都是確定的在32位的編譯器下指針變量的大小都是4個(gè)字節(jié),在64位編譯器下指針的大小都是8個(gè)字節(jié)?為啥呢?要知道不管什么類型的指針都是指針變量,而指針變量都是用來存放地址的,所以指針變量的大小取決一個(gè)地址存放所需要的空間大小為此不同的編譯器有不同的大小但一般都是4/8個(gè)字節(jié)。
1.4指針的定義和使用:#includeint main()
{
int a=10; //在內(nèi)存中申請空間 我們也知道局部變量是存放在棧中的
int* p=&a; //定義一個(gè)指針,對變量a取地址用的符號是&,這里a占的字節(jié)是四個(gè),這里是將a的4個(gè)字節(jié)的第一個(gè)字節(jié)的地址存放在p變量中,p就是一個(gè)之指針變量。
printf("%d\n",*p); //*p是對指針的解引用,得到地址所指向的數(shù)
printf("%p\n",p); //這里可以得到p的地址
return 0;
}
1.5野指針:1.5.1 什么是野指針:野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒有明確限制的)
1.5.2野指針形成的原因:
<1>沒有初始化
#includeint main()
{
int *p; //局部變量的指針沒有初始化,默認(rèn)隨機(jī)值 這就是個(gè)野指針
return 0;
}
<2>數(shù)組的越界
#includeint main()
{
int arr[5]={1,2,3,4,5}
int* p=arr;
for(int i=0;i<6;i++)
{
* (p++)=i;
}
return 0;
}
<3>指針指向的空間釋放
#include#includeint main()
{
int *p=(int*)malloc(40);
free(p);
return 0;
}
1.5.3如何避免野指針:
<1>. 指針初始化
<2>. 小心指針越界 <3>.? 指針指向空間釋放即使置 NULL <4>. 避免返回局部變量的地址 <5>. 指針使用之前檢查有效性 二、指針的進(jìn)階認(rèn)識: 2.1字符指針:#includeint main()
{
char ch='m';
char *pr=&ch; //存放字符的指針
const char *pr1="hello xiaoma" //存放字符串的指針,他是存放字符傳的第一個(gè)地址并不是全部地址的存放.
//為什要加個(gè)const 要知道權(quán)限不能被擴(kuò)大,只能被縮小,*pr1指向的是數(shù)組常量不能被改變所以用const來進(jìn)行修飾。
printf("%c %s\n",*pr,pr1); //打印字符,和字符串
return 0;
}
2.2指針數(shù)組:2.2.1:指針數(shù)組,重點(diǎn)在于數(shù)組,是用來存放指針的數(shù)組。
int* arr[10]; 存放整型指針的數(shù)組
double* arr1[10];存放double型指針的數(shù)組
char* arr[10] ; 存放字符型指針的數(shù)組
2.2.2指針數(shù)組的應(yīng)用,可以吧幾個(gè)一維數(shù)組合并成一個(gè)二維數(shù)組一樣。
#includeint main()
{
int arr1[]={1,2,3,4};
int arr2[]={3,4,5,6};
int arr3[]={7,8,9,10};
int* arr[3]={arr1,arr2,arr3};
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
return 0;
}
2.3數(shù)組指針:2.3.1 數(shù)組指針,重點(diǎn)在于指針,他是指向數(shù)組的指針。
int arr[10]={0};
int *p=arr //這里表示p指向arr首元素的地址。這里是整型指針
int (*p1)[10]=&arr; //這里表示p1指向整個(gè)數(shù)組的地址 這是數(shù)組指針
2.3.2 數(shù)組指針的應(yīng)用:數(shù)組指針不怎么用在一維指針上大多是用在二維或者三維指針上
#includevoid print(int (*p)[3],int x,int y)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%d ",*(*(p+i)+j)); //先對p解引用表示指向第一行的地址 加i就是指向第i行的地址 加j表示指向第j列的地址 最后在解引用就得到數(shù)值
}
printf("\n");
}
}
int main()
{
int arr[3][3]={1,2,3,2,3,4,3,4,5};
print(arr,3,3);
return 0;
}
2.4函數(shù)指針:2.4.1通過數(shù)組指針我們類比函數(shù)指針,數(shù)組指針是指向數(shù)組的指針,那么函數(shù)指針呢,就是指向函數(shù)的指針。
int Add(int x,int y)
{
return x+y;
}
int (*p)(int,int)=&Add; //這就是定義一個(gè)函數(shù)指針p指向的就是Add函數(shù)的地址,沒錯(cuò)函數(shù)也是有自己的地址的
2.4.2函數(shù)指針的簡單應(yīng)用:
#includeint Add(int x,int y)
{
return x+y;
}
int Sub(int x,int y)
{
return x-y; // 這是為了我們更好的理解函數(shù)指針的應(yīng)用,所以寫的比較簡單。
}
int Mul(int x,int y)
{
return x*y;
}
int Div(int x,int y)
{
return x/y;
}
void Func(int (*p)(int ,int ),int x,int y)//傳的是函數(shù)指針
{
int ret = p(x,y);
printf("%d\n",ret);
} //可能覺得沒什么用 看一下復(fù)雜的應(yīng)用就知道指針函數(shù)的應(yīng)用
int main()
{
Func(Add,2,3);
Func(Sub,2,3);
Func(Mul,3,3); //這里就是一個(gè)函數(shù)來實(shí)現(xiàn)了加減乘除 而要一個(gè)函數(shù)實(shí)現(xiàn)四個(gè)函數(shù)的功能則需要運(yùn)用函數(shù)指針
Func(Div,6,2);
return 0;
}
2.4.3函數(shù)指針的復(fù)雜應(yīng)用:
?~~回調(diào)函數(shù):回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè) 函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù) 的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對該事件或條件進(jìn) 行響應(yīng)。
我們上面實(shí)現(xiàn)的簡單應(yīng)用就是一個(gè)回調(diào)函數(shù),而現(xiàn)在我們要實(shí)現(xiàn)一個(gè)比較復(fù)雜的回調(diào)函數(shù):
qsort函數(shù),我們先去了解一下qsort函數(shù)怎么使用,這里我比較推薦一個(gè)網(wǎng)站就是專門用來查看c/c++庫函數(shù):https://legacy.cplusplus.com/https://legacy.cplusplus.com/這里我們來簡單的講述qsort函數(shù):qsort的函數(shù)是通過快排的方法來實(shí)現(xiàn)不同類型的排序問題,我們來通過代碼展示他的使用并且自己來實(shí)現(xiàn)一個(gè)qsort函數(shù)
#include#include#includeint swap(const void*p1,const void*p2)
{
return *(int*)p1-*(int*)p2;
}
int main()
{
int arr[10]={1,3,6,2,5,4,8,7,10,9};
int sz=sizeof(arr)/sizeof(arr[0]); //求數(shù)組的長度
qsort(arr,sz,sizeof(int),swap); //第一個(gè)要傳排序?qū)ο蟮牡刂?,然后排序的長度,寬度,最后排序的判斷方法。
for(int i=0;i
在用qsort按名字排一個(gè)結(jié)構(gòu)體:
#include#include#includestruct Student
{
char name[20];
int age ;
};
int swap(const void*p1,const void*p2)
{
return strcmp(((struct Student*)p1)->name,((struct Student*)p2)->name);
}
int main()
{
struct Student arr[]={{"xiaomma",18},{"lisi",17},{"wanger",20}};
int sz=sizeof(arr)/sizeof(arr[0]);
qsort(arr,sz,sizeof(struct Student),swap);
for(int i=0;i
創(chuàng)建自己的qsort函數(shù)m_qsort :
這里m_qsort我用的是冒泡法,雖然效率低了,但是我們要掌握的是函數(shù)指針的用法!
void Swap(char*buf1,char*buf2,int width){ int i=0; for(i=0;i
0) { Swap ((char*)base+j*width,(char*)base+(j+1)*width,width); //因?yàn)楸容^類型不同所以用char傳地址比較好,char才占一個(gè)地址,我們知道總長度也知道寬度就好進(jìn)行交哈。 } } } } int cmp_int(const void* e1,const void*e2) { return (*(int *)e1-*(int *)e2); } int main() { int arr[]={9,8,7,6,5,4,3,2,1,0}; int sz=sizeof(arr)/sizeof(arr[0]); bubble_sort(arr,sz,sizeof(arr[0]),cmp_int); for(int i=0;i
代碼很長但很有必要自己來實(shí)現(xiàn)一下就能夠深入的理解函數(shù)指針存在的意義啦,如果要有不理解的地方可以直接問我的。^?_?^
2.5函數(shù)指針數(shù)組:?2.5.1函數(shù)指針數(shù)組也就是存放函數(shù)指針的數(shù)組。
??
int Add(int x,int y)
{
return x+y;
}
int (*p)(int ,int )=&Add //函數(shù)指針
int (*arr[4])(int,int ); //函數(shù)指針數(shù)組 //通過對比我們就很容易發(fā)現(xiàn)就是把p換成一個(gè)數(shù)組 他的類型就是函數(shù)指針數(shù)組
int (*(*prr)[5])(int ,int )//函數(shù)指針數(shù)組的指針。哈哈哈哈類似于套娃是的 就是便于大家取了解這個(gè)東西
2.5.2函數(shù)指針數(shù)組的應(yīng)用:也是很容易的可以把我們上面寫的四個(gè)功能用一遍
#includeint Add(int x,int y)
{
return x+y;
}
int Sub(int x,int y)
{
return x-y;
}
int Mul(int x,int y)
{
return x*y;
}
int Div(int x,int y)
{
return x/y;
}
int main()
{
int i=0;
int (*arr[])(int ,int )={Add,Sub,Mul,Div};
for(i=0;i<4;i++)
{
printf("%d\n",arr[i](6,2));
}
return 0;
}
總結(jié):1、從指針的初級指針是什么,和如何使用到指針的進(jìn)階一大堆不同的指針,這里小馬都已經(jīng)全部寫完,還有一個(gè)結(jié)構(gòu)體指針,我覺得看過我的鏈表就應(yīng)該很容易的掌握,這里我都不進(jìn)行寫啦,我覺得比較難的點(diǎn)就在于函數(shù)指針這里的qsort函數(shù)自己的實(shí)現(xiàn),我認(rèn)為很有必要多看幾遍自己在寫一遍,才能深入理解qsort函數(shù),和函數(shù)指針。
2、最后碼文不易,如果覺得文章有幫助的話,請多多關(guān)注,希望我們能夠一同進(jìn)步,共同發(fā)展!?。?!^?_?^
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧