接著上次的函數(shù)的基本知識(shí),今天我們來講一講??指針
目錄
一、指針的概念
二、指針變量
三、野指針
四、字符指針
五、指針與數(shù)組
六、指針數(shù)組
七、數(shù)組指針
?八、指針與函數(shù)
總結(jié)
一、指針的概念
1.1、變量和地址
所謂指針,也就是內(nèi)存的地址;所謂指針變量,也就是保存了內(nèi)存地址的變量。
總結(jié):指針就是變量,用指針存放地址(口語中說的指針通常指的是指針變量)?
1.2、指針變量和指針的類型
指針變量就是一個(gè)變量,它存儲(chǔ)的內(nèi)容是一個(gè)指針。在我們定義一個(gè)變量的時(shí)候,要確定它的類型。在定義指針變量時(shí)也是一樣的,必須確定指針類型。int 變量的指針需要用 int 類型的指針存儲(chǔ),float 變量的指針需要用 float 類型的指針存儲(chǔ)。
?指針類型決定了:指針解引用的權(quán)限有多大與指針走一步走多大字節(jié)(步長(zhǎng))
整型指針+1跳過一個(gè)整型。字符指針+1跳過一個(gè)字符
二、指針變量
2.1、指針變量的定義及使用
(1)指針變量的定義
指針變量的定義形式如:數(shù)據(jù)類型 *指針名;例如:
int* x;//整型指針變量
float* f;//浮點(diǎn)型指針變量
char* ch;//字符型指針變量
指針的變量名分別是:x;f和ch。而int*;float*與char*分別是他們中存儲(chǔ)的數(shù)據(jù)的類型。?
(2)指針變量的使用
取地址運(yùn)算符&:?jiǎn)文窟\(yùn)算符&是用來取操作對(duì)象的地址。例:&i 為取變量 i 的地址。對(duì)于常量表達(dá)式、寄存器變量不能取地址(因?yàn)樗鼈兇鎯?chǔ)在存儲(chǔ)器中,沒有地址)。
指針運(yùn)算符*(解引用運(yùn)算符 ):與&為逆運(yùn)算,作用是通過操作對(duì)象的地址,獲取存儲(chǔ)的內(nèi)容。例:x = &i,x 為 i 的地址,*x 則為通過 i 的地址,獲取 i 的內(nèi)容。
//聲明了一個(gè)普通變量 a
int a;
//聲明一個(gè)指針變量,指向變量 a 的地址
int *pa;
//通過取地址符&,獲取 a 的地址,賦值給指針變量
pa = &a;
//通過間接尋址符,獲取指針指向的內(nèi)容
printf("%d", *pa);
2.2、指針運(yùn)算
(1)指針與整數(shù)的加減運(yùn)算
指針變量的自增自減運(yùn)算。指針加 1 或減 1 運(yùn)算,表示指針向前或向后移動(dòng)一個(gè)單元(不同類型的指針,單元長(zhǎng)度不同)。
(2)指針減指針
前提是兩個(gè)指針指向同一個(gè)空間。
指針減指針得到兩個(gè)指針間的元素個(gè)數(shù)
例: Arr[9]指向9與10中間部分(下標(biāo))
三、野指針
3.1概念:
野指針就是指針指向的為止是不可知的(隨機(jī)的,不正確的,沒有明確限制的)
3.2野指針的成因
(1)指針未初始化
(2)指針越界
如圖:在第十次 訪問時(shí),可以進(jìn)入到循環(huán),相當(dāng)于從第10個(gè)點(diǎn)向后訪問4個(gè)字節(jié),之后的字節(jié)不屬于原數(shù)組,則越界了,則稱為野指針。(只有在超出范圍后,在會(huì)發(fā)生崩潰)
//越界訪問
*int arr[10] ={ 0 };
int* p = arr;
int i=0;
for (i=0; i <= 10; i++)//共執(zhí)行了11次,而arr數(shù)組總共只有10個(gè)元素
{
*p = i;
p++;
}
(3)指針指向的空間釋放
int* test()//局部變量
{
int a = 10;
return &a;
}
int main()
{
int *p=test();//返回值是a的地址,而局部變量在引用之后就會(huì)銷毀。
*p = 20;
return 0;
}
3.3如何規(guī)避野指針
1.指針初始化?
2.小心指針越界。
3.指針指向空間釋放即置NULL
4.指針使用之前檢查有效性。
四、字符指針
int main()
{
? ?const char* pstr = "hello ";//這里是把一個(gè)字符串放到pstr指針變量里了嗎?
? ?printf("%s\n", pstr);
? ?return 0; }
本質(zhì)是把字符串 hello首字符的地址放到了pstr中。
4.2例題
int main()
{
? ?char str1[] = "hello bit.";
? ?char str2[] = "hello bit.";
? ?const char *str3 = "hello bit.";
? ?const char *str4 = "hello bit.";
? ?if(str1 ==str2)
printf("str1 and str2 are same\n");
? ?else
printf("str1 and str2 are not same\n");
? ? ?
? ?if(str3 ==str4)
printf("str3 and str4 are same\n");
? ?else
printf("str3 and str4 are not same\n");
? ? ?
? ?return 0;
}
最終輸出的結(jié)果是
這里str3和str4指向的是一個(gè)同一個(gè)常量字符串。C/C++會(huì)把常量字符串存儲(chǔ)到單獨(dú)的一個(gè)內(nèi)存區(qū)域。當(dāng)幾個(gè)指針指向同一個(gè)字符串的時(shí)候,他們實(shí)際會(huì)指向同一塊內(nèi)存。但是用相同的常量字符串去初始化不同的數(shù)組的時(shí)候就會(huì)開辟出不同的內(nèi)存塊。所以str1和str2不同,str3和str4不同。?
五、指針與數(shù)組
之前我們可以通過下標(biāo)訪問數(shù)組元素,學(xué)習(xí)了指針之后,我們可以通過指針訪問數(shù)組的元素。在數(shù)組中,數(shù)組名即為該數(shù)組的首地址,結(jié)合上面指針和整數(shù)的加減,我們就可以實(shí)現(xiàn)指針訪問數(shù)組元素。
5.1、指針與二維數(shù)組
(1)二維數(shù)組的地址
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p=a[0];//此處的p內(nèi)存放的數(shù)組a第一行的地址。
5.2、多級(jí)指針
(1)多級(jí)指針(指向指針的指針)
指針變量作為一個(gè)變量也有自己的存儲(chǔ)地址,而指向指針變量的存儲(chǔ)地址就被稱為指針的指針,即二級(jí)指針。依次疊加,就形成了多級(jí)指針。
指針變量也是一種變量,也會(huì)占用存儲(chǔ)空間,也可以使用 &獲取它的地址。C語言不限制指針的級(jí)數(shù),每增加一級(jí)指針,在定義指針變量時(shí)就得增加一個(gè)星號(hào) *。p1 是一級(jí)指針,指向普通類型的數(shù)據(jù),定義時(shí)有一個(gè) *;p2 是二級(jí)指針,指向一級(jí)指針 p1,定義時(shí)有兩個(gè)*。例:假設(shè)有一個(gè) int 類型的變量 a,p1是指向 a 的指針變量,p2 又是指向 p1 的指針變量,它們的關(guān)系如下圖所示:
六、指針數(shù)組
1.parr的第一個(gè)數(shù)組里放arr1的首元素地址
2.parr每個(gè)元素的類型是int*。
3.該數(shù)組里每個(gè)元素都是指針,所以它是一個(gè)指針數(shù)組
4.Parr[i][j],也可以寫成parr[i]+j,
5.相當(dāng)于地址+j為向后挨個(gè)元素指向
七、數(shù)組指針
7.1、數(shù)組指針的定義
如以下語句:
int (*p)[10];
//解釋:p先和*結(jié)合,說明p是一個(gè)指針變量,然后指著指向的是一個(gè)大小為10個(gè)整型的數(shù)組。
//所以p是一個(gè)指針,指向一個(gè)數(shù)組,叫數(shù)組指針。
//這里要注意:[]的優(yōu)先級(jí)要高于*號(hào)的,所以必須加上()來保證p先和*結(jié)合。
?7.2、&數(shù)組名與數(shù)組名
讓我們看一段代碼
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0;
}
?運(yùn)行結(jié)果如下
根據(jù)上面的代碼我們發(fā)現(xiàn),其實(shí)&arr和arr,雖然值是一樣的,但是意義應(yīng)該不一樣的。
實(shí)際上: &arr 表示的是數(shù)組的地址,而不是數(shù)組首元素的地址。(細(xì)細(xì)體會(huì)一下)
本例中 &arr 的類型是: int(*)[10] ,是一種數(shù)組指針類型。
數(shù)組的地址+1,跳過整個(gè)數(shù)組的大小。
?7.3、數(shù)組指針的使用
#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)//形參用數(shù)組來接受
{
? ?int i = 0;
? ?for(i=0; i<row; i++)
? {
? ? ? ?for(j=0; j<col; j++)
? ? ? {
? ? ? ? ? ?printf("%d ", arr[i][j]);
? ? ? }}}
void print_arr2(int (*arr)[5], int row, int col)//形參用數(shù)組指針來接受
{
? ?int i = 0;
? ?for(i=0; i<row; i++)
? {
? ? ? ?for(j=0; j<col; j++)
? ? ? {printf("%d ", arr[i][j]);}
? ? ? ?printf("\n");}}
int main()
{
? int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
? print_arr1(arr, 3, 5);
? ?//數(shù)組名arr,表示首元素的地址
? ?//但是二維數(shù)組的首元素是二維數(shù)組的第一行
? ?//所以這里傳遞的arr,其實(shí)相當(dāng)于第一行的地址,是一維數(shù)組的地址
? ?//可以數(shù)組指針來接收
? ?print_arr2(arr, 3, 5);
? ?return 0; }
?八、指針與函數(shù)
8.1、函數(shù)指針的定義??
returnType (*pointerName)(param list);
其中,returnType 為函數(shù)返回值類型,pointerNmae 為指針名稱,param list 為函數(shù)參數(shù)列表。參數(shù)列表中可以同時(shí)給出參數(shù)的類型和名稱,也可以只給出參數(shù)的類型,省略參數(shù)的名稱,這一點(diǎn)和函數(shù)原型非常類似。
注意( )的優(yōu)先級(jí)高于*,第一個(gè)括號(hào)不能省略,如果寫作returnType *pointerName(param list);就成了函數(shù)原型,它表明函數(shù)的返回值類型為returnType *。
8.2、指向函數(shù)的指針int (*pf[4])(int,int)={Add,Sub,Mul,Div};
函數(shù)指針數(shù)組,在函數(shù)指針的基礎(chǔ)上,將指針變?yōu)橹羔様?shù)組
總結(jié)
以上就是初階指針的基本內(nèi)容了!?。?!非常感謝你能看到這里!文章來源:http://www.zghlxwxcb.cn/news/detail-402522.html
如果你覺得你有些想法和我一樣,想和我一起提升自己可以關(guān)注私信我,與我一起進(jìn)步,一起共同努力?。。。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-402522.html
到了這里,關(guān)于【C語言】指針的基本知識(shí)詳細(xì)講解(指針數(shù)組、數(shù)組指針、函數(shù)指針....的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!