详解指针

什么是指针

先看百科中怎么解释

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为”指针”。意思是通过它能找到以它为地址的内存单元。 在高级语言中,指针有效地取代了在低级语言,如汇编语言与机器码,直接使用通用暂存器的地方,但它可能只适用于合法地址之中。指针参考了存储器中某个地址,通过被称为反参考指针的动作,可以取出在那个地址中存储的值。作个比喻,假设将电脑存储器当成一本书,一张内容记录了某个页码加上行号的便利贴,可以被当成是一个指向特定页面的指针;根据便利粘贴面的页码与行号,翻到那个页面,把那个页面的那一行文字读出来,就相当于是对这个指针进行反参考的动作。

我对于指针的理解

指针,就是一个指向内存地址的变量,指针也是变量,和int、float等一样,只不过指针存的是地址,通俗的说,指针就是类似于门牌号码的作用,给出具体的门牌号就知道这个房子在哪,给出具体指针,指针里面存的地址会告诉你变量所在的位置,通过解引用符号(*)对指针进行解引用,就可以知道指针指向的变量的内容

定义指针

举几个例子:

    int    *pi = NULL;
    char   *pc = NULL;
    long   *pl = NULL;
    short  *ps = NULL;
    float  *pf = NULL;
    double *pd = NULL;
可以总结出一个规律,指针变量的定义是:type *变量名

PS:当然,这个规律暂时我们先认为他是正确的,后面会有不符合这个规律的指针定义,比如函数指针和数组指针

理清概念

指针也是变量!
指针也是变量!
指针也是变量!
我们通常说的都是定义一个指针,这句话完整的话应该说定义一个指针变量,这是书面语和日常用语的区别,我们可以说定义一个指针,但我们要明白我们定义的是指针变量。
因为指针也是变量,所以指针也占空间,32位机器下指针大小为4个字节,无论它是什么类型

指针加减

指针加一加的其实加的是指向类型空间的大小
指针类型决定了指针向前或向后走一步有多大
例如:
int *pi;
pi + 1其实加的是int的大小,即越过四个字节的大小
char *pc;
pc + 1其实是加char的大小,即越过一个字节的大小

而在同一个字符串或者数组内,两指针相减结果是中间所间隔元素个数

测试代码:

int main()
{
    int n = 0;
    int *pi = &n;
    char *pc = (char*)&n;

    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int *start = &arr[0], *end = &arr[10];
    //arr[10]指向数组最后一个元素的后面

    printf("     n:%#p\n", &n);
    printf("    pi:%#p\n", pi);
    printf("  pi+1:%#p\n", pi + 1);
    printf("    pc:%#p\n", pc);
    printf("  pc+1:%#p\n", pc + 1);

    printf("end - start:%d\\n", end - start);
    system("pause");
    return 0;
}

jo-qzy的博客

二级指针

指向指针的指针
如何定义:
int ** ppi = NULL;
这个指针可以指向一个一级指针,例:

    int n = 0;
    int* pi = &n;
    int** ppi = π

指针数组和数组指针

指针数组是数组,数组指针是指针
指针数组是存了一堆指针的数组,数组指针是指向一个数组的指针
如何通过指针变量的定义去辨别他们
我们只需要记住三个字:优先级

[]的优先级比*的优先级高,先和什么结合,就是什么类型
先和[]结合就是数组,先和*结合就是指针

int *p[10];
//指针数组,数组里面存了十个指针,每个指针可以指向一个整形变量
int (*p)[10];
//数组指针,可以指向一个有十个元素的整形数组

指针数组的应用:转移表(过了考试周更新)

函数指针

变量有地址,其实函数也有地址,因而有函数指针
函数指针的定义比较特殊:
类型 + (* 变量名)(参数表);
举个例子:

    void (* pv)(int, char*);
    //定义一个叫pv的函数指针指向一个无返回值的函数,他的参数列表为一个整型和一个char型指针
    int (* pi)(int, int);
    //定义一个叫pi的函数指针指向一个返回值为整形的函数,他的参数列表为两个整型
    _CRTIMP void __cdecl qsort(void*, size_t, size_t,int (*)(const void*, const void*));
    //库函数中的qsort函数就有函数指针变量的定义

在qsort函数中就有使用函数指针作为变量
(如果你想了解更多关于qsort,你可以点击下面的链接进入我的另一篇博客)
函数指针实例:使用冒泡排序模拟实现qsort的功能
我们把这种将函数指针作为参数传入的方法叫做回调函数

通过定义辨别指针数组和数组指针

牢记三个字 : ”优先级”
先判断和谁结合,将其写在最后,然后往前写
举个例子:

void ((*pv)[5])(int, char* );
先看结合,pv*结合,这是一个指针
1、指针
接下来看与[]结合,于是我们在指针前面加上数组
2、数组 + 指针
现在我们知道他是个数组指针,但我们没有判断出他的类型
接下来判断类型,很明显这是一个函数指针的类型
所以最后我们的结果
3、一个指向 函数指针 数组指针

是不是很容易?我们再做一个

void (*signal(int, void(*)(int))(int)
先找变量,这里的变量名字有点长,他是signal(int, void(*)(int))
signal内部的参数表其实也包含了一个函数指针
看他与谁结合,*
1、这是一个指针
2、判断类型,函数指针

如果你还不明白,再做一个

int *((*(*p)[2])[10])[5];
先看和谁结合,*
1、指针
接下来和[2]结合
2、数组+指针
接下来和*结合
3、指针+数组+指针
接下来和[10]结合
4、数组+指针+数组+指针
接下来和[5]结合
5、数组+数组+指针+数组+指针
最后和*结合
6、指针+数组+数组+指针+数组+指针
整理一下,就是一个指向整型指针数组的数组指针的数组指针

如果到这解释了还不会。。那我也没办法了

函数指针数组

    void (* pv[5])(int, char* );
    //定义一个叫pv的函数指针数组,数组中每个元素指向一个无返回值的函数,他的参数列表为一个整型和一个char型指针
    int (* pi[5])(int, int);
    //定义一个叫pi的函数指针数组,数组中每一个元素指向一个返回值为整形的函数,他的参数列表为两个整型

指向函数指针数组的指针

    void ((*pv)[5])(int, char* );
    //定义一个叫pv的函数指针数组指针,指向一个存有五个函数指针的数组,数组则是无返回值得函数指针数组,参数为一个int和一个char*
    int ((*pi)[5])(int, int);
    //定义一个叫pi的函数指针数组指针,指向一个存有五个函数指针的数组,数组则是返回整型数,参数为两个整型的函数指针数组

数组传参

数组传参,会发生降级,传入的参数是其内部元素类型的指针
所有数组都可以认为是一维数组
什么意思呢?
就是说,如果有一个三维数组,可以看成一维数组,每个元素是一个二维数组
而这个三维数组在传参时,传入的就是一个二维数组指针

一维数组传参
int main()
{
    int arr[5];
    test(arr);
}

void test(int arr[]);//正确
{}

void test(int arr[10]);//正确,但是没有人会蠢到明明五个却写十个,还不如不写
{}

void test(int *arr);//正确
{}

void test(int *arr[5]);//错误
{}

一维指针数组传参

int main()
{
    int *arr[5];
    test(arr);
}

void test(int **arr);//正确
{}

void test(int *arr[5]);//正确
{}
二维数组传参
int main()
{
    int arr[5][10];
    test(arr);
}

void test(int arr[5][10]);//正确
{}

void test(int arr[][10]);//正确
{}

void test(int (*arr)[10]);//错误
{}

void test(int arr[][]);//错误
{}

void test(int **arr);//错误
{}
关于指针的知识不只有这么多,需要在平时代码中多加练习,这篇文章写在此帮助不明白指针的同学理解指针,以及帮助自己记忆和理解指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值