成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【指針套娃】指針進(jìn)階詳解

番茄西紅柿 / 3178人閱讀

摘要:三數(shù)組指針數(shù)組指針的定義數(shù)組指針是指針還是數(shù)組答案是指針。所以數(shù)組指針應(yīng)該是能夠指向數(shù)組的指針。首先函數(shù)指針是一個(gè)指針需要先與結(jié)合然后在與結(jié)合表明指向一個(gè)函數(shù)里面放函數(shù)的形參類型。

前言

首先我們?cè)賮砘仡櫼幌轮羔樀母拍?/p>

  1. 指針就是個(gè)變量,用來存放地址,地址唯一標(biāo)識(shí)一塊內(nèi)存空間。
  2. 指針的大小是固定的4/8個(gè)字節(jié)(32位平臺(tái)/64位平臺(tái))。
  3. 指針是有類型,指針的類型決定了指針的+(-)整數(shù)的步長(zhǎng),指針解引用操作的時(shí)候的權(quán)限。
  4. 指針的運(yùn)算。

一、字符指針

字符指針一般有兩種:

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相同。

二、指針數(shù)組

前面我們也學(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ù)組指針的定義

數(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;}

&數(shù)組名VS數(shù)組名

對(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é):

  • arr(不屬于兩個(gè)例外)和&arr[0]都是首元素地址
  • &arr是數(shù)組的地址,而不是數(shù)組首元素的地址,所以 &arr+1是跳過整個(gè)數(shù)組(40個(gè)字節(jié))
  • 首元素地址+1是第二個(gè)元素的地址
  • sizeof(arr)是求得整個(gè)數(shù)組大小
  • 是地址大小都為4/8

數(shù)組指針的使用

那數(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ù)的指針,存放函數(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ù)組

類似于指針數(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類型。

函數(shù)指針數(shù)組的應(yīng)用——轉(zhuǎn)移表

轉(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ù)組的指針

指向函數(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ù)

定義

回調(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)。

#includeint 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;}


總結(jié)

指針是C語(yǔ)言的一大特點(diǎn)和難點(diǎn),它可以無限套娃,我們需要深刻理解他們的性質(zhì)才能學(xué)懂并使用它。

希望能對(duì)你理解深入的指針有所幫助!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/122423.html

相關(guān)文章

  • 指針學(xué)習(xí)進(jìn)階

    摘要:讓我們來看一下代碼,首先我們還是冒泡排序一樣,進(jìn)行了兩次循環(huán),第一次代表排序趟數(shù),第二次代表每趟的排序次數(shù)。這塊的詳細(xì)介紹在本篇文章稍前的冒泡排序中也有詳細(xì)介紹。 ...

    oysun 評(píng)論0 收藏0
  • 五分鐘殺穿指針 pointer——C語(yǔ)言專題

    摘要:另外,通過指針可以更便捷地操作數(shù)組。在一定意義上可以說,指針是語(yǔ)言的精髓。野指針成因除了未初始化還有就是越界訪問或者指針指向空間已經(jīng)釋放。所以不難知道兩個(gè)地址相減就是元素的個(gè)數(shù),這個(gè)表達(dá)式的前提是兩個(gè)指針指向同一塊空間。 ...

    MycLambert 評(píng)論0 收藏0
  • C語(yǔ)言指針篇(一篇文章讓你不再暈“針”)?。?!

    摘要:指針的大小在位平臺(tái)是個(gè)字節(jié),在位平臺(tái)是個(gè)字節(jié)。比如的指針解引用就只能訪問一個(gè)字節(jié),而的指針的解引用就能訪問四個(gè)字節(jié)。所以是一個(gè)指針,指向一個(gè)數(shù)組,叫數(shù)組指針。 準(zhǔn)備...

    zsirfs 評(píng)論0 收藏0
  • 手撕C語(yǔ)言進(jìn)階---字符串和內(nèi)存函數(shù)(詳解+實(shí)現(xià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...

    vslam 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<