指针

2018-11-09  本文已影响38人  yuan6441952

1、什么是指针?

通俗来讲——指针就是变量,用来储存地址的变量。

2、指针数组 & 数组指针

指针数组:它是一个数组,数组里面每个元素都是指针,数组的大小由它元素的个数决定。 

数组指针:它是一个指针,它指向一个数组,指针的大小永远都是4字节 。

(1)int *p1[10] 

p1是指针数组,里面有10个元素,每个元素都是地址;

(2)int (*p2)[10] 

p2是数组指针,这个指针指向一个有10个整型元素的数组。

两者区分:

①我们要知道“[ ]”的优先级比“ * ”的优先级高,p1先与“[ ]”先集合,这就构成了数组的结构,数组名是p1,里面存的元素的类型是 int *

②p2先和“ * ”结合,构成指针结构,指针名为p2,int和[10]共同表示指针的类型,p2指向的是具有10个整型元素的数组。

3、a和&a的区别

int main()

{

    char a[5] = { 'a', 'b', 'c', 'd', 'e' };

    char(*p1)[5] = &a;

    char(*p2)[5] = a;

    return 0;

}

p1和p2哪个是数组指针?

此处p1和p2都是数组指针,但最好采用p1这种写法。 因为a是代表数组首元素的地址,而&a才是代表整个数组的地址,两者的值是一样的,但所代表的意义是完全不同的。

4、地址强转

下面代码输出结果是多少?

int main()

{

    int a[4] = { 1, 2, 3, 4 };

    int *p1 = (int *)(&a + 1);

    int *p2 = (int *)((int)a + 1);

    printf("%x, %x", p1[-1], *p2);

    return 0;

}

p1:把 &a+1的值强制转换成 int * 再赋值给p1,此时p1指向数组a尾元素的下一个int型元素。p1[-1]可以理解成 *(p1 - 1)。表示p1往前移动sizeof(int)个字节,所以输出0x4。

p2:(int)a + 1表示把a强转成整型数据,再加1则(int)a + 1就是元素a[0]的第二个字节的地址,然后再把这个地址强转为int * 类型赋值给p2,那*p2的值就是从元素a[0]的第二个字节开始的连续4字节的内容。

那么这连续4个字节内容是什么呢?这里就要区分大小端了,小端模式返回0x2000000;大端模式返回0x100。

注:

所谓的大端模式,就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

所谓的小端模式,就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

5、函数指针

函数指针还是一个指针,它指向的是一个函数,这个指针变量里存的是一个函数的地址。

char * ( *fun)(char *p1, char *p2);

这里定义了一个函数指针,指针名为fun,指向函数fun,这个函数的返回值类型是 char *,参数是char *p1, char *p2。

函数指针数组:

char * ( *pf)(char *p)这里定义了一个函数指针 pf,既然如此那把这个指针放到数组里,这就形成了一个函数指针数组:

char * ( * pf[10])(char *p)

①数组名:pf

②数组元素:10个指向函数的指针。

③每个指针指向一个函数

④函数的返回类型为指向字符的指针,参数为一个指向字符的指针。

函数指针数组的用途:转移表

函数指针数组指针:

函数指针数组指针就是一个指针, 这个指针指向一个数组,这个数组里存的是指向函数的指针。

char * ( * (*pf)[10]) (char * p)

①这里定义了一个函数指针数组指针,指针变量名是pf。

②指针指向一个有10个元素的数组。

③数组里存的都是指向函数的指针。

④ 这些指针每个都指向一些函数。

⑤指向的函数的返回值类型为指向字符的指针,参数为一个指向字符的指针。

记忆方法:

函数指针数组指针数组指针。

我们从右往左分析:

①指针:*pf

②数组指针:(* pf)[5]

③指针数组指针:(* (* pf) )[5]

④数组指针数组指针:( (* (* pf) )[5])[3]

⑤指针数组指针数组指针:( * ( (* (* pf) )[5]) )[3]

⑥函数指针数组指针数组指针:void * ( ( * ( (* (* pf) )[5]) )[3] ) ( )

分析(*(void(*)())0)()

①void(*)() 是一个函数指针类型,这个函数无参数,无返回值。

②(void(*)())0 把0强转成函数指针类型,0是一个函数的首地址。

③(*(void(*)())0) 把地址为0的函数取出来。

④(*(void(*)())0)(),函数调用。

上一篇下一篇

猜你喜欢

热点阅读