C/C++指针

指针的概念

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。所有指针在32位上都是4个字节,在64位系统是8个字节。

为什么要用指针

1)指针的使用使得不同区域的代码可以轻易的共享内存数据,这样可以使程序更为快速高效;

2)C语言中一些复杂的数据结构往往需要使用指针来构建,如链表、二叉树等;

3)C语言是传值调用,而有些操作传值调用是无法完成的,如通过被调函数修改调用函数的对象,但是这种操作可以由指针来完成,而且并不违背传值调用。

六大常用指针

int *arr; //单指针

int **arr; //双重指针,指向指针的指针

int (*arr)[3]; //数组指针,指向int型的的一维数组

int *arr[3];          //指针数组,该数组有3个元素,每个元素都是一个指向int型对象的指针

int (*arr)(int, int); //函数指针,指向一个有两个int参数的函数

int *arr(int, int); //指针函数,函数的返回类型为int型指针

技巧:是指针都是变量单独带括号,优先级:()>[]>*,后面以指针结尾,其就是指针。

怎么解析复杂指针?

右左法则:首先从最里面的圆括号(应该是未定义的标识符)看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。

int (*func)(int *p);

首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是 int。

int (*func)(int *p, int (*f)(int*));

func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。

int (*func[5])(int *p);

func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰 func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。
int (* (*func) [5] ) (int *p);

func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。

int (*(*func)(int *p))[5];

func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。

int (*(*func)[5][6])[7][8];

func是一个指向数组的指针,这类数组的元素是一个具有5X6个int元素的二维数组,而这个二维数组的元素又是一个二维数组。typedef分解:

typedef int (*PARA)[7][8];
typedef PARA (*func)[5][6];

int (*(*(*func)(int *))[5])(int *);

func是一个函数指针,这类函数的返回值是一个指向数组的指针,所指向数组的元素也是函数指针,指向的函数具有int*形参,返回值为int。typedef分解:

typedef int (*PARA1)(int*);
typedef PARA1 (*PARA2)[5];
typedef PARA2 (*func)(int*);

int (*(*func[7][8][9])(int*))[5];

func是一个指针数组,这个数组的元素是函数指针,这类函数具有int*的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。typedef分解:

typedef int (*PARA1)[5];
typedef PARA1 (*PARA2)(int*);
typedef PARA2 func[7][8][9];

复杂指针的宏替换

过于复杂的指针,会给他人阅读代码带来麻烦,一般会使用宏定义来替换复杂的指针

举个例子:

//int *(*(*fun)(int*))[10];

typedef int *Arr[10];
typedef Arr*(pFun)(int*);

Arr* myfun(int *)
{
    static int a[10]={1,2,3,4,5,6,7,8,9,10};
    static int* array[10];
    for (int i = 0; i < 10; i++)
    {
        array[i]=&a[i];
    }
    return &array;
}

void main()
{
    pFun fun;
    fun=&myfun;
}

同样,以下函数可以写为:

//int(*func)(int*,int(*),pFun pf);
typedef int(*pFun)(int*);
typedef int(*pFunType)(int*,pFun pf);
pFunType func;

//int (*func[5])(int *);
typedef int (*pFun)(int *);
pFun func[5];

//int (*(*func)[5])(int *); 
typedef int (*pFun)(int *);
typedef pFun (*Func)[5];
Func func;

//int (*(*func)(int *))[5];
typedef int *Ar[5];
typedef Ar *(*pFun)(int *);
pFun fun;

//int *(*func(int *))[5]
typedef int *Ar[5];
Ar *func(int *);

野指针

不是NULL指针,是指向垃圾内存的指针

    1.声明一个指针没有进行合法的初始化

    2.free后,没有置NULL

指针与const

const int *p = &a;    //p所指向的内容不能改变,指针可以改变
int const *p1 = &a;    //p1所指向的内容不能改变,指针可以改变
int *const p2 = &a;    //p2指针不能改变,内容可变 
const int *const p3=&a;    //p3指针不能改变,内容不能改变
posted @ 2019-08-01 00:54  WindSun  阅读(275)  评论(0编辑  收藏  举报
博客已停更,文章已转移,点击访问