摘要:三數(shù)組指針數(shù)組指針的定義數(shù)組指針是指針還是數(shù)組答案是指針。所以數(shù)組指針應(yīng)該是能夠指向數(shù)組的指針。首先函數(shù)指針是一個(gè)指針需要先與結(jié)合然后在與結(jié)合表明指向一個(gè)函數(shù)里面放函數(shù)的形參類型。
首先我們?cè)賮砘仡櫼幌轮羔樀母拍?/p>
字符指針一般有兩種:
int main(){ //第一種,指向單個(gè)字符 char ch='w'; char* p=&ch; //第二種,指向一個(gè)常量字符串 char* ptr="hello world!";//但是ptr存放的是整個(gè)字符串嗎? return 0;}
特別容易以為是把常量字符串 hello world! 放到字符指針 ptr 里了,但是本質(zhì)是把字符串 首字符的地址放到了ptr中,也就是說ptr指向的是’h’的地址,但是字符串在內(nèi)存中是連續(xù)存儲(chǔ),且串末尾系統(tǒng)自動(dòng)加上’/0’結(jié)尾,所有當(dāng)用%s輸出字符串時(shí),它會(huì)從第一個(gè)元素持續(xù)輸出到’/0’結(jié)束。
那就有這樣的面試題:
#include int main(){ char str1[] = "hello world!"; char str2[] = "hello world!"; char *str3 = "hello world!"; char *str4 = "hello world!"; 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;}
請(qǐng)?jiān)谛闹心畛瞿愕拇鸢浮?/p>
從上面知道,字符指針,數(shù)組指針存放的都是元素的首地址,所以比較的就是首地址。
這里str3和str4指向的是一個(gè)同一個(gè)常量字符串。C/C++會(huì)把常量字符串存儲(chǔ)到多帶帶的一個(gè)內(nèi)存區(qū)域,當(dāng)幾個(gè)指針。指向同一個(gè)字符串的時(shí)候,他們實(shí)際會(huì)指向同一塊內(nèi)存。但是用相同的常量字符串去初始化不同的數(shù)組的時(shí)候就會(huì)開辟出不同的內(nèi)存塊。所以str1和str2不同,str3和str4相同。
前面我們也學(xué)習(xí)了指針數(shù)組
這里我們?cè)購(gòu)?fù)習(xí)一下,下面指針數(shù)組是什么意思?
int* arr1[10]; //整形指針的數(shù)組(存放整形指針)char *arr2[4]; //一級(jí)字符指針的數(shù)組(存放字符指針)char **arr3[5];//二級(jí)字符指針的數(shù)組(存放二級(jí)字符指針)
如何判斷數(shù)組存放的類型呢?
很簡(jiǎn)單,直接去掉” 數(shù)組名[] “剩下的就是數(shù)組存放的類型。
數(shù)組指針是指針?還是數(shù)組?
答案是:指針。
我們可以根據(jù)以往的學(xué)習(xí)來推導(dǎo),字符指針char* p,整型指針int* p。
所以數(shù)組指針應(yīng)該是:能夠指向數(shù)組的指針。
那如何來表示呢
首先它是一個(gè)指針,那定義時(shí)就需要在變量前加*,其次它指向的類型又是一個(gè)數(shù)組,所以有以下定義
int arr[10]={0};//定義一個(gè)數(shù)組指針parr指向arrint (*parr)[10]=&arr;//*parr必須用括號(hào)括起來,因?yàn)閇]的優(yōu)先級(jí)高于*
也可以是從表達(dá)式來解釋
parr先和*結(jié)合,說明parr是一個(gè)指針變量,然后指著指向的是一個(gè)大小為10個(gè)整型的數(shù)組。所以p是一個(gè)指針,指向一個(gè)數(shù)組,叫數(shù)組指針。
int main(){ int a = 10; int* pi = &a;//整型的地址存放在整型指針中 char ch = 'w'; char* pc = &ch;//字符的地址存放在字符指針中 int arr[10] = {0}; int* p = arr;// -是數(shù)組首元素的地址 //int* parr[10]; //這樣寫是數(shù)組 int (*parr)[10] = &arr;//取出的是數(shù)組的地址, 應(yīng)該存放到數(shù)組指針中 return 0;}
對(duì)于下面的數(shù)組:
int arr[10];
arr 和 &arr 分別是啥?
我們知道arr是數(shù)組名,數(shù)組名表示數(shù)組首元素的地址。
那&arr數(shù)組名到底是啥?
我們看一段代碼:
#include int main(){ int arr[10] = {0}; printf("%p/n",&arr[0]); printf("%p/n", arr); printf("%p/n", &arr); return 0;}
他們的值是一樣的
所以我們可以得出結(jié)論,此時(shí)的&arr和arr都是指向數(shù)組首元素,是首元素的地址,要注意的一點(diǎn)是他們的類型不同,分別是int ()[10]和int*。
但任何時(shí)候arr都是指向數(shù)組首元素嗎?
給出結(jié)論:arr在不同的地方有不同的含義。
當(dāng)數(shù)組名(arr)除以下兩種情況外都是首元素地址
1. sizeof(數(shù)組名), 這里的數(shù)組名是表示整個(gè)數(shù)組的,sizeof(數(shù)組名)計(jì)算的是整個(gè)數(shù)組的大小,單位是字節(jié)
2. &數(shù)組名, 這里的數(shù)組名不是首元素的地址,數(shù)組名表示整個(gè)數(shù)組,所以取出的是整個(gè)數(shù)組的地址
代碼如下:
#include int main(){ int arr[10] = { 0 }; //計(jì)算整個(gè)數(shù)組大小 printf("%d/n", sizeof(arr)); //取出來的地址是整個(gè)數(shù)組的地址 int(*parr)[10] = &arr; return 0;}
我們來看一下區(qū)別
#include int main(){ int arr[10] = { 0 }; //arr是首元素地址 //&arr[0]是首元素地址 //&arr取出數(shù)組的地址 printf("%p/n",arr ); printf("%p/n",&arr[0] ); printf("%p/n", &arr); printf("%p/n", arr+1); printf("%p/n", &arr[0]+1); printf("%p/n", &arr+1); printf("%d/n", sizeof(arr)); printf("%d/n", sizeof(&arr)); int(*parr)[10] = &arr; return 0;}
總結(jié):
那數(shù)組指針是怎么使用的呢?
既然數(shù)組指針指向的是數(shù)組,那數(shù)組指針中存放的應(yīng)該是數(shù)組的地址。
看代碼:
#include int main(){ int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int (*p)[10] = &arr;//把數(shù)組arr的地址賦值給數(shù)組指針變量p //但是我們一般很少這樣寫代碼 return 0;}
也就是指向函數(shù)的指針,存放函數(shù)的地址。
來看一段代碼
#include void test(){ printf("hehe/n");}int main(){ printf("%p/n", test); printf("%p/n", &test); return 0;}
兩個(gè)的值都是函數(shù)的地址。那怎么保存函數(shù)的地址呢?
需要定義一個(gè)函數(shù)指針來接收函數(shù)的地址。
首先函數(shù)指針是一個(gè)指針,需要先與 * 結(jié)合,然后在與 () 結(jié)合,表明指向一個(gè)函數(shù),()里面放函數(shù)的形參類型。還有函數(shù)的返回值。
void test(){ printf("hehe/n");}//下面pfun1和pfun2哪個(gè)有能力存放test函數(shù)的地址?void (*pfun1)();void *pfun2();
void (*pfun1)();//先和*結(jié)合,是一個(gè)指針,()表示指向一個(gè)函數(shù),void表示函數(shù)的返回值。void *pfun2();//先和()結(jié)合,是函數(shù)的聲明,返回值是void*。
int Add(int x,int y){ return x + y;}//定義函數(shù)指針int (*p)(int, int)=Add;//也可int (*p)(int, int)=&Add;//使用指針調(diào)用函數(shù)int ret = p(3, 4);int ret = (*p)(3, 4);
兩段有趣的代碼
//代碼1(*(void (*)())0)();// void (*)() 是一個(gè)函數(shù)指針類型,函數(shù)無返回值,無參//首先將整數(shù)0的類型強(qiáng)制轉(zhuǎn)換為一個(gè)函數(shù)指針,此時(shí)0就是一個(gè)函數(shù)指針,存放函數(shù)的地址,然后對(duì)0解引用,再()調(diào)用函數(shù),被調(diào)用的函數(shù),無參//所以這個(gè)代碼是一次函數(shù)調(diào)用//代碼2void (*signal(int , void(*)(int)))(int);//首先signal先和()結(jié)合,是一個(gè)函數(shù),函數(shù)的參數(shù)有兩個(gè),一個(gè)類型是int,一個(gè)類型是 void(*)(int) 函數(shù)指針類型,既然是函數(shù)就應(yīng)該有返回類型//把signal(int , void(*)(int)),去掉后就是函數(shù)的返回類型 void(*)(int) ,是一個(gè)函數(shù)指針,該函數(shù)返回類型為空,參數(shù)為空。//所以語(yǔ)句本質(zhì)是一個(gè)函數(shù)聲明//函數(shù)名是signal
函數(shù)指針類型看著很復(fù)雜,也不方便使用,我們可以使用 typedef 定義一個(gè)別名
//我們知道typedef int DataType;//類似定義typedef void(* pfun )(int);//pfun就是類型別名//我們可以直接使用,來定義函數(shù)指針變量pfun pAdd = &Add;//同樣也可以把上述void (*signal(int , void(*)(int)))(int);簡(jiǎn)化pfun signal(int, pfun);
類似于指針數(shù)組,把函數(shù)的地址存到一個(gè)數(shù)組中,那這個(gè)數(shù)組就叫函數(shù)指針數(shù)組,那函數(shù)指針的數(shù)組如何定義呢?
首先,是一個(gè)數(shù)組,那就要先和下標(biāo)運(yùn)算符[]結(jié)合,其次才是函數(shù)指針類型
int (* arr[10])(int, int);//數(shù)組有十個(gè)元素,每個(gè)元素類型是int (*)(int, int) 函數(shù)指針,該函數(shù)返回類型是int,有兩個(gè)參數(shù),都是int類型。
轉(zhuǎn)移表
也就是將返回類型,參數(shù)個(gè)數(shù)和類型相同的函數(shù)放在一個(gè)數(shù)組里面,然后應(yīng)對(duì)不同的情況使用數(shù)組來調(diào)用每個(gè)函數(shù)。
例如,定義加、減、乘、除四個(gè)函數(shù),他們的返回類型,參數(shù)個(gè)數(shù)和類型相同,將他們放在一個(gè)數(shù)組里面。
int (* arr[4])(int, int)={add, sub, mul, div };//調(diào)用int ret = (*p[input])(x, y);
指向函數(shù)指針數(shù)組的指針是一個(gè) 指針 指針指向一個(gè) 數(shù)組 ,數(shù)組的元素都是 函數(shù)指針。
定義
首先它是一個(gè)指針,先與 * 結(jié)合-(*parr),然后再和 [] 結(jié)合,表明指向一個(gè)數(shù)組- (*parr)[4],然后是數(shù)組的元素類型-函數(shù)指針 int (*) (int, int)
int (*(*parr)[4])(int, int) = &arr;
定義
回調(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)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。
#include int Add(int x, int y){ return x + y;}int Sub(int x, int y){ return x - y;}void test(int (*pfun)(int, int)){ int ret = pfun(3, 4);//通過函數(shù)指針去調(diào)用其他函數(shù) printf("%d/n", ret);}int main(){ test(Add);//將函數(shù)的地址作為參數(shù) test(Sub); return 0;}
希望能對(duì)你理解深入的指針有所幫助!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/122423.html
摘要:讓我們來看一下代碼,首先我們還是冒泡排序一樣,進(jìn)行了兩次循環(huán),第一次代表排序趟數(shù),第二次代表每趟的排序次數(shù)。這塊的詳細(xì)介紹在本篇文章稍前的冒泡排序中也有詳細(xì)介紹。 ...
摘要:另外,通過指針可以更便捷地操作數(shù)組。在一定意義上可以說,指針是語(yǔ)言的精髓。野指針成因除了未初始化還有就是越界訪問或者指針指向空間已經(jīng)釋放。所以不難知道兩個(gè)地址相減就是元素的個(gè)數(shù),這個(gè)表達(dá)式的前提是兩個(gè)指針指向同一塊空間。 ...
摘要:指針的大小在位平臺(tái)是個(gè)字節(jié),在位平臺(tái)是個(gè)字節(jié)。比如的指針解引用就只能訪問一個(gè)字節(jié),而的指針的解引用就能訪問四個(gè)字節(jié)。所以是一個(gè)指針,指向一個(gè)數(shù)組,叫數(shù)組指針。 準(zhǔn)備...
摘要:自己實(shí)現(xiàn)時(shí)返回值可根據(jù)實(shí)際情況而定源字符串必須以結(jié)束。語(yǔ)言中給了一些長(zhǎng)度受限的字符串函數(shù),而前面的函數(shù)是長(zhǎng)度不受限的字符串函數(shù)??截悅€(gè)字符從源字符串到目標(biāo)空間。 目錄 字符函數(shù)和字符串函數(shù) 函數(shù)介紹 strlen strcpy strcat strcmp strncpy ?strncat s...
閱讀 740·2023-04-25 19:43
閱讀 3986·2021-11-30 14:52
閱讀 3816·2021-11-30 14:52
閱讀 3873·2021-11-29 11:00
閱讀 3808·2021-11-29 11:00
閱讀 3907·2021-11-29 11:00
閱讀 3584·2021-11-29 11:00
閱讀 6197·2021-11-29 11:00