成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

保姆式教學(xué)--指針的進(jìn)階-創(chuàng)新互聯(lián)

在這里插入圖片描述

創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的平泉網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

共和國的的建設(shè)者可要好好學(xué)好指針哦!

文章目錄
  • 引入!
  • 1、 字符指針
  • 2、 指針數(shù)組
  • 3、 數(shù)組指針
    • 3.1 數(shù)組指針的定義
    • 3.2 &數(shù)組名VS數(shù)組名
    • 3.3 數(shù)組指針的使用
  • 4、 數(shù)組傳參和指針傳參
    • 4.1一維數(shù)組傳參
    • 4.2二維數(shù)組傳參
    • 4.3一級指針傳參
    • 4.4二級指針傳參
  • 5、 函數(shù)指針
  • 6、 函數(shù)指針數(shù)組
  • 7、 指向函數(shù)指針數(shù)組的指針
  • 8、 回調(diào)函數(shù)

引入!
1. 指針就是個(gè)變量,用來存放地址,地址唯一標(biāo)識一塊內(nèi)存空間。
2. 指針的大小是固定的4/8個(gè)字節(jié)(32位平臺(tái)/64位平臺(tái))。
3. 指針是有類型,指針的類型決定了指針的+-整數(shù)的步長,指針解引用操作的時(shí)候的權(quán)限。
4. 不同數(shù)據(jù)類型的指針之間唯一的不同是,指針?biāo)赶虻淖兞炕虺A康臄?shù)據(jù)類型不同。
5. 指針的運(yùn)算。

在這里插入圖片描述

1、 字符指針

在指針的類型中我們知道有一種指針類型為字符指針 char* ;
一般使用:

int main()
{char ch = 'w';
  char *pc = &ch;
  *pc = 'w';
  return 0;
}

還有一種使用方式如下:

int main()
{const char* pstr = "hello bit.";//這里并不是把一個(gè)字符串放到pstr指針變量里,而是將字符串的首字符的地址放到了pstr中。
  printf("%s\n", pstr);
  return 0;
}

`直接上題目練習(xí),在題目中深度了解字符指針

//輸出什么?
#includeint main()
{char str1[] = "hello bit.";//————————1
  char str2[] = "hello bit.";//————————2
  const char *str3 = "hello bit.";//————————3
  const char *str4 = "hello bit.";//————————4
  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;
}

答案:
在這里插入圖片描述

分析:1和2分別創(chuàng)建了一個(gè)全新的數(shù)組,再進(jìn)行比較的時(shí)候,操作系統(tǒng)會(huì)對他們的本質(zhì),即首字符地址,進(jìn)行比較,既然是兩個(gè)數(shù)組,那么他們的首字符地址一定不同(雙胞胎都有不同的基因),所以拿1和2進(jìn)行比較的時(shí)候會(huì)輸出“str1 and str2 are not same”
str3是一個(gè)字符指針,指針的本質(zhì)是字符串首字符的地址,str3、str4兩個(gè)指針指向的都是同一個(gè)字符串的首字符的地址,所以str3和str4是相同的。
如何理解?:一家人有一個(gè)共同的家,通過一家三口中的每一個(gè)人我們都能找到這個(gè)家。
所以此時(shí)會(huì)輸出“str3 and str4 are same”

再來一題關(guān)于const的使用的重要性

int main()
{char* pstr= "hello bit.";
	*pstr = "666";
	printf("%s\n", pstr);
	return 0;
}

輸出:在這里插入圖片描述
為什么這里我們沒有任何輸出?
分析:字符串首字符的地址首先傳給了pstr,程序繼續(xù)進(jìn)行,走到27行,pstr被更改了,但是指針pstr仍是“h”的地址,內(nèi)容變?yōu)椤?66”,此時(shí)進(jìn)行輸出,操作系統(tǒng)無法判斷出輸出內(nèi)容。
假設(shè)我們使用了const進(jìn)行修飾:

int main()
{const char* pstr= "hello bit.";
	*pstr = "666";//————5
	printf("%s\n", pstr);
	return 0;
}

在這里插入圖片描述

5處在編譯器里會(huì)有提示,提示表達(dá)式左側(cè)必須為可以修改的標(biāo)量,所以,媽媽再也不用擔(dān)心我的pstr會(huì)被改變了,在實(shí)際中大大增強(qiáng)了安全性、實(shí)用性。
結(jié)論:合理使用const進(jìn)行限制可以減少某些bug的產(chǎn)生。

2、 指針數(shù)組
類比:
整型數(shù)組————存放整形的數(shù)組
字符數(shù)組————存放字符的數(shù)組
得出:
指針數(shù)組————存放指針(地址)的數(shù)組
int* arr1[10]; //整形指針的數(shù)組
char *arr2[4]; //一級字符指針的數(shù)組
char **arr3[5];//二級字符指針的數(shù)組
const char *arr[4]={"EDG","AG","QG","AE"};//字符指針數(shù)組

在這里插入圖片描述
模擬二重?cái)?shù)組

#includeint arr1[4]={1,2,3,4};
int arr2[4]={2,3,4,5};
int arr3[4]={3,4,5,6};
int arr4[4]={4,5,6,7};
int *arr[4]={arr1,arr2,arr3,arr4};
for(int i=0;i<=4;i++)
{for(int j=0;j<=4;j++)
	{printf("%d",arr[i][j]);
		//printf("%d",*(arr[i]+j));
	}
}

在這里插入圖片描述

3、 數(shù)組指針 3.1 數(shù)組指針的定義

數(shù)組指針是指針?還是數(shù)組?
答案是:指針。
我們已經(jīng)熟悉:
整形指針: int * pint; 能夠指向整形數(shù)據(jù)的指針。
浮點(diǎn)型指針: float * pf; 能夠指向浮點(diǎn)型數(shù)據(jù)的指針。
那數(shù)組指針應(yīng)該是:能夠指向數(shù)組的指針

int*p; //整形指針
float*q;//浮點(diǎn)型指針
int(*b)[];//數(shù)組指針
解釋:p先和*結(jié)合,說明p是一個(gè)指針變量,然后指著指向的是一個(gè)大小為10個(gè)整型的數(shù)組。所以p是一個(gè)
指針,指向一個(gè)數(shù)組,叫數(shù)組指針。
這里要注意:[]的優(yōu)先級要高于*號的,所以必須加上()來保證p先和*結(jié)合。
3.2 &數(shù)組名VS數(shù)組名

對于下面的數(shù)組:

int arr[10]; 	

arr 和 &arr 分別是啥?
我們知道arr是數(shù)組名,數(shù)組名表示數(shù)組首元素的地址。
那&arr數(shù)組名到底是啥?
我們看一段代碼:

#includeint main()
{int arr[10] = {0};
  printf("%p\n", arr);
  printf("%p\n", &arr);
  return 0;
}

在這里插入圖片描述
可見數(shù)組名和&數(shù)組名打印的地址是一樣的。
難道兩個(gè)是一樣的嗎?
我們再看一段代碼:

#includeint main()
{int arr[10] = {0 };
printf("arr = %p\n", arr);
printf("arr = %p\n", arr+1);

printf("&arr= %p\n", arr[0]);
printf("arr+1 = %p\n", arr[0]+1);

printf("&arr+1= %p\n", &arr);
printf("&arr+1= %p\n", &arr+1);
return 0;
}

在這里插入圖片描述

分析:

根據(jù)上面的代碼我們發(fā)現(xiàn),其實(shí)&arr和arr,雖然值是一樣的,但是意義是不一樣的.
事實(shí)上,&arr表示的是整個(gè)數(shù)組的地址,而arr僅僅表示數(shù)組首元素的地址,因?yàn)?arr表示整個(gè)數(shù)組的地址,所以才有&arr+1跳過整個(gè)數(shù)組的大小

3.3 數(shù)組指針的使用

那數(shù)組指針是怎么使用的呢?
既然數(shù)組指針指向的是數(shù)組,那數(shù)組指針中存放的應(yīng)該是數(shù)組的地址。
來樣例:

#includevoid ErWei(int arr[2][3],int m,int n)
{for(int i=0;ifor(int j=0;j	printf("%d",arr[i][j]);
		}
		printf("\n")
	}
}
int main()
{int arr[2][3]={1,2,3,4,5,6};
	ErWei(arr,2,3);
  return 0;
}

在這里插入圖片描述

4、 數(shù)組傳參和指針傳參 4.1一維數(shù)組傳參
1:C語言中,當(dāng)一維數(shù)組做函數(shù)參數(shù)時(shí),編譯器總是把它解析成一個(gè)指向其首元素的指針。
2:實(shí)際傳遞的數(shù)組大小與函數(shù)形參指定的數(shù)組大小沒有關(guān)系。
3:數(shù)組傳參本質(zhì)上傳遞的是數(shù)組首元素的地址。
4:一維數(shù)組傳參可以由:
	4.1  一維數(shù)組接受
	4.2  一級或二級指針接受
	4.3  指針數(shù)組接受
4.2二維數(shù)組傳參
二維數(shù)組作為參數(shù)傳遞到函數(shù)有三種方式:
1:直接傳遞
2:指針傳遞,將二維數(shù)組的第一行傳遞
3:利用二級指針進(jìn)行傳遞

如下形式都是允許的:

void test(int arr[3][5])
{}
void test(int arr[][5])
{}
//總結(jié):二維數(shù)組傳參,函數(shù)形參的設(shè)計(jì)只能省略第一個(gè)[]的數(shù)字。
//因?yàn)閷σ粋€(gè)二維數(shù)組,可以不知道有多少行,但是必須知道一行多少元素。
//這樣才方便運(yùn)算
void test(int (*arr)[5])
int main()
{int arr[3][5] = {0};
test(arr);
}
4.3一級指針傳參

直接上題目:
當(dāng)一個(gè)函數(shù)的參數(shù)部分為一級指針的時(shí)候,函數(shù)能接收什么參數(shù)?

答案:
		1、(地址類)一級指針變量
		2、(地址類)一維數(shù)組數(shù)組名
		3、(地址類)整型變量
4.4二級指針傳參

直接上題目
當(dāng)函數(shù)的參數(shù)為二級指針的時(shí)候,可以接收什么參數(shù)?

答案:(本質(zhì)上都是地址)
		1、二級指針變量
		2、數(shù)組名
		3、一級指針變量地址
5、 函數(shù)指針

先推理:
數(shù)組指針:指向數(shù)組的指針

int (*p)[10];

函數(shù)指針:指向函數(shù)的指針

int (*p)(void,void);//p就是一個(gè)存放函數(shù)地址的指針

再看代碼:

#includevoid test()
{printf("hehe\n");
}
int main()
{printf("%p\n", test);
	printf("%p\n", &test);
	return 0;
}

在這里插入圖片描述
輸出的是兩個(gè)地址,這兩個(gè)地址是 test 函數(shù)的地址。
結(jié)論:函數(shù)名和&函數(shù)名都是函數(shù)的地址
保存test的方式:

void (*pfun1)()=&test;

寫一個(gè)簡單的函數(shù)指針:

#includevoid Add(int x, int y)
{return x + y;
}
int main()
{int (*pf)(int,int) = &Add;
	//int (*pf)(int,int)=Add;
	int ret = (*pf)(2, 3);
	//int ret=pf(2,3);
	printf("%d", ret);
}

在這里插入圖片描述
《C陷阱和缺陷》中的題目:大家做著玩吧

//分析代碼題目:
//代碼1
(*(void (*)())0)();
//代碼2
void (*signal(int , void(*)(int)))(int);

結(jié)束函數(shù)指針。

6、 函數(shù)指針數(shù)組

前面我們已經(jīng)學(xué)習(xí)了函數(shù)指針

int(*p)(void,void);

數(shù)組是一個(gè)存放相同類型數(shù)據(jù)的存儲(chǔ)空間,那要把函數(shù)的地址存到一個(gè)數(shù)組中,那這個(gè)數(shù)組就叫函數(shù)指針數(shù)組
在這里理解起來函數(shù)指針數(shù)組不會(huì)是困難的事情,我們先來瞧瞧函數(shù)指針數(shù)組的樣子:

int (*p[10])(void,void)

p 先和 [] 結(jié)合,說明 p是數(shù)組,數(shù)組的內(nèi)容是什么呢?
是 int (*)() 類型的函數(shù)指針。
函數(shù)指針數(shù)組的用途:轉(zhuǎn)移表
直接給兄弟們上例子:
未使用函數(shù)指針數(shù)組做轉(zhuǎn)移表的計(jì)算器是非常臃腫的:

#includevoid menu()
{printf("***********************************\n");
		printf("************1.Add  2.Sub***********\n");
		printf("************3.Mul  4.Div***********\n");
		printf("************5.exit******************\n");
		printf("***********************************\n");
		printf("***********************************\n");
}
int 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 input = 0;

	do
	{int ret = 0;
		int x, y = 0;
		menu();
		printf("你要進(jìn)行什么計(jì)算:");
		scanf_s("%d", &input);
		switch (input)
		{case 1:
		{	printf("請輸入操作數(shù):");
			scanf_s("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
		}
			break;

		case 2:
			printf("請輸入操作數(shù):");
			scanf_s("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("請輸入操作數(shù):");
			scanf_s("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("請輸入操作數(shù):");
			scanf_s("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("已退出");
		default:
			printf("請重新輸入");
			break;
         }
	} while (input);
	return 0;
}

此時(shí)我們加上函數(shù)指針數(shù)組用作轉(zhuǎn)移表:

#includevoid menu()
{printf("***********************************\n");
		printf("************1.Add  2.Sub***********\n");
		printf("************3.Mul  4.Div***********\n");
		printf("************5.exit******************\n");
		printf("***********************************\n");
		printf("***********************************\n");
}
int 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 input = 0;
	int ret = 0;
	int x, y = 0;
	do
	{menu();
		printf("請選擇功能:");
		scanf_s("%d", &input);
		if (input >= 0&&input<=4)
		{	printf("請輸入操作數(shù):");
			scanf_s("%d %d", &x, &y);
			int (*pf[5])(int, int) = {NULL,Add,Sub,Mul,Div };
			ret = pf[input](x, y);
			printf("%d\n", ret);
		}
		else
		{	printf("請重新輸入......\n");
		}


	} while (input);
}

在這里插入圖片描述
結(jié)論:代碼2更加簡潔,代碼量更少,功能實(shí)現(xiàn)與1相同,而且2更讓你更加便于后期增加功能。

7、 指向函數(shù)指針數(shù)組的指針

聽起來比較繞,但理解起來只需要在函數(shù)指針數(shù)組的基礎(chǔ)上再加上一個(gè)指針,如下:

int(*p[10])(int,int);//函數(shù)中指針數(shù)組
int(*(*pp)[10])(int,int);//指向函數(shù)指針數(shù)組的指針

是不是很簡單啊!

8、 回調(diào)函數(shù)

先來看看來自維基百科的對回調(diào)(Callback)的解析:
In computer programming, a callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time. This execution may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback.
再來看看來自Stack Overflow某位大神簡潔明了的表述:
A “callback” is any function that is called by another function which takes the first function as a parameter。 也就是說,函數(shù) F1 調(diào)用函數(shù) F2 的時(shí)候,函數(shù) F1 通過參數(shù)給 函數(shù) F2 傳遞了另外一個(gè)函數(shù) F3 的指針,在函數(shù) F2 執(zhí)行的過程中,函數(shù)F2 調(diào)用了函數(shù) F3,這個(gè)動(dòng)作就叫做回調(diào)(Callback),而先被當(dāng)做指針傳入、后面又被回調(diào)的函數(shù) F3 就是回調(diào)函數(shù)。到此應(yīng)該明白回調(diào)函數(shù)的定義了吧?

機(jī)制
⑴定義一個(gè)回調(diào)函數(shù);
⑵提供函數(shù)實(shí)現(xiàn)的一方在初始化的時(shí)候,將回調(diào)函數(shù)的函數(shù)指針注冊給調(diào)用者;
⑶當(dāng)特定的事件或條件發(fā)生的時(shí)候,調(diào)用者使用函數(shù)指針調(diào)用回調(diào)函數(shù)對事件進(jìn)行處理

實(shí)例:用回調(diào)函數(shù)改進(jìn)基礎(chǔ)版計(jì)算器

#includevoid menu()
{printf("***********************************\n");
		printf("************1.Add  2.Sub***********\n");
		printf("************3.Mul  4.Div***********\n");
		printf("************5.exit******************\n");
		printf("***********************************\n");
		printf("***********************************\n");
}
int 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;
}
void calc (int(*pf)(int, int))
{int ret = 0;
	int x = 0;
	int y = 0;
	printf("請輸入操作數(shù):");
	scanf_s("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}
int main()
{int input = 0;

	do
	{menu();
		printf("你要進(jìn)行什么計(jì)算:");
		scanf_s("%d", &input);
		switch (input)
		{case 1:
			calc(Add);
			break;

		case 2:
			calc(Sub);
			break;
		case 3:
			calc(Mul);
			break;
		case 4:
			calc(Div);
			break;
		case 0:
			printf("已退出");
		default:
			printf("請重新輸入");
			break;
         }
	} while (input);
	return 0;
}

在這里插入圖片描述
回調(diào)函數(shù)結(jié)束。

本期就講到這里。下期見友友們!
在這里插入圖片描述

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

本文題目:保姆式教學(xué)--指針的進(jìn)階-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://jinyejixie.com/article42/cshchc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、域名注冊動(dòng)態(tài)網(wǎng)站、小程序開發(fā)、全網(wǎng)營銷推廣網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)
会宁县| 洛南县| 长汀县| 农安县| 嘉黎县| 白河县| 涪陵区| 涪陵区| 石渠县| 来宾市| 新密市| 黎川县| 杭州市| 伊吾县| 安乡县| 阿合奇县| 孟村| 龙门县| 张家港市| 青铜峡市| 安陆市| 太白县| 稷山县| 镇江市| 花垣县| 神木县| 金寨县| 宁乡县| 丰都县| 会泽县| 高清| 甘泉县| 黄大仙区| 斗六市| 宁晋县| 北辰区| 泰宁县| 灵寿县| 绥棱县| 汽车| 元谋县|