招商網(wǎng)站建設(shè)多少錢合肥seo報(bào)價(jià)
前言
????????指針變量的解引用和加法運(yùn)算是非常高頻的考點(diǎn),也是難點(diǎn),因?yàn)閷?duì)初學(xué)者的不友好,這就導(dǎo)致了各大考試都很喜歡在這里出題,通常會(huì)伴隨著強(qiáng)制類型轉(zhuǎn)換、二維數(shù)組、數(shù)組指針等一起考查大家對(duì)指針的理解。但是不要怕,也許看完這篇文章你有了新的認(rèn)識(shí)和理解,寫的不透徹的地方也希望大家多多指正
理解:指針變量的解引用
我們分下面兩步理解:
- 解引用,拿出來的是什么?
- 解引用,根據(jù)什么拿出來的?
1. 拿出來的是什么
????????首先解引用拿出來的就是指針指向的內(nèi)容,比如指針p指向的是這個(gè)地址,*p就是拿出來地址里面的內(nèi)容;
2. 根據(jù)什么拿出來的
????????指針的類型決定了,對(duì)指針解引用的時(shí)候有多大的權(quán)限(能拿出幾個(gè)字節(jié))。
#include <stdio.h>
int main()
{int a = 40000;int *p = &a;printf("%d\n", *(char*)p);return 0;
}
本應(yīng)該是40000的值,咋變成64了?這其實(shí)就跟解引用的指針類型有關(guān)了,但是這里還涉及了一個(gè)知識(shí)點(diǎn)是大小端,上面是小端的結(jié)果,小端就是低位在低地址,高位在高地址;大端反之,所以會(huì)有不同的結(jié)果;因?yàn)榻庖檬菑牡偷刂烽_始的;大端結(jié)果就應(yīng)該是0
#include <stdio.h>
int main()
{int a = 40000;int *p = &a;printf("%d\n", *p);return 0;
}
所以這里就是直接解引用了4個(gè)字節(jié),只要是涉及多個(gè)字節(jié)了,取出來的要按照低位還是低位來算,切記不能以為先取出來的就是高位;
理解:指針變量的加法
我們來分這兩步理解:
- 指針變量的加法,加的是什么?
- 指針變量的加法,是根據(jù)什么來加的?
1. 加的是什么
????????我們首先來分析指針變量是什么,指針變量是一個(gè)地址,那指針變量的加法,實(shí)際上就是對(duì)這個(gè)指針變量代表的地址做加法,也就是向后移動(dòng)指針變量指向的位置,讓指向的地址更高。
2. 根據(jù)什么來加
? ? ? ? 指針變量的加法是根據(jù):指針變量的數(shù)據(jù)類型實(shí)現(xiàn)的;
指針 + n = 指針 + n*指針類型中的除*的類型所占字節(jié)
char*就是n
int*就是4n
比如:char*類型
char c = 0;
char *pc = &c;
printf("pc = %p\n", pc);
printf("pc + 1 = %p\n", pc + 1);
我們可以看到pc+1的值是向后移動(dòng)了1個(gè)字節(jié)
比如:int*類型
int i = 0;
int *pi = &i;
printf(" pi = %p\n", pi);
printf("pi+1 = %p\n", pi + 1);
此時(shí)int類型的pi+1的值是向后移動(dòng)了4個(gè)字節(jié)
比如:double*類型
double d = 0;
double *pd = &d;
printf(" pd = %p\n", pd);
printf("pd+1 = %p\n", pd + 1);
此時(shí)double類型的pd+1的值是向后移動(dòng)了8個(gè)字節(jié)
例題
1.?普通的加法
#include <stdio.h>
int main()
{int arr[5] = {1, 2, 3, 4, 5};int *p = arr;printf("%d\n", *(p + 1));printf("%d\n", p[1]);return 0;
}
答案及解析:2 2
首先p指向的是arr,arr是數(shù)組名,代表的是首元素的地址,所以p指向的就是首元素的地址
p數(shù)據(jù)類型為int*,p+1就是向后移動(dòng)4*1個(gè)字節(jié),到達(dá)arr[1]的地址,解引用是取4個(gè)字節(jié),取到的就是arr[1];
p既然是首元素地址,那p和arr就沒區(qū)別,所以p[1] 等價(jià)于 arr[1],為2;
2. 包含強(qiáng)制類型轉(zhuǎn)換的加法
#include <stdio.h>
int main()
{int arr[5] = {1, 2, 3, 4, 5};int *p = arr;printf("%d\n", *((char*)p + 1));printf("%d\n", *((short*)p + 2));return 0;
}
答案及解析:0 2
這時(shí)候我們必須要用二進(jìn)制來表示數(shù)字,因?yàn)檫@里涉及到了強(qiáng)制類型轉(zhuǎn)換;此時(shí)加法和解引用都會(huì)受到影響。所以這里的第一個(gè)輸出語句,是先強(qiáng)制類型轉(zhuǎn)換成char*類型,然后一直是對(duì)char*類型的指針進(jìn)行加法和解引用,這里我一直按小端講解
而我們的第二個(gè)輸出語句則是強(qiáng)制轉(zhuǎn)換short*,加法和解引用都是2字節(jié)
3. 包含二維數(shù)組和數(shù)組指針的加法
#include <stdio.h>
int main()
{int arr[2][2] = {{1, 2}, {3, 4}};int (*p)[2] = arr;printf("%d\n", **(p + 1));return 0;
}
在這里首先要知道二維數(shù)組名代表的是什么,我們必須清楚一個(gè)邏輯
二維數(shù)組是一維數(shù)組的數(shù)組,也就是說可以把二維數(shù)組看成存放一維數(shù)組的數(shù)組;
這樣說肯定很抽象,我們看圖:
二維數(shù)組名代表的是第一行的地址,也就是代表整個(gè)第一行,相當(dāng)于&arr[0],那二維數(shù)組名就是一個(gè)數(shù)組指針了,因?yàn)閿?shù)組指針也是表示的一個(gè)數(shù)組的地址;所以我們可以定義一個(gè)數(shù)組指針p = arr;那p + 1,就要慎重了,p的數(shù)據(jù)類型是int (*)[2],所以p+1,就是移動(dòng)整個(gè)數(shù)組的大小,所以p+1 就指向的是arr[1]這個(gè)數(shù)組,p + 1 = &arr[1],所以解引用一次就是取到了整個(gè)數(shù)組arr[1],但是*(p + 1) = arr[1],arr[1]是這個(gè)二維數(shù)組的行,相當(dāng)于該行這個(gè)一維數(shù)組的數(shù)組名,既然是一維數(shù)組的數(shù)組名,就是首元素地址,那就是int*類型,再解引用就是解引用4字節(jié),拿到的就是3.