C语言中对指针的深刻理解

1.指针是什么?

很多小伙伴可能对C语言的指针有误解,以为指针看起来很复杂,其实不然,其实指针是内存中一个最小单元的编号,也就是地址。平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。

我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址放到一个变量中,这个变量就是指针变量。

总结:指针变量,用来存放地址的,地址是唯一标示一块空间的。而且指针大小在64位平台是8个字节;在32位平台下是4个字节。cao

2.指针和指针类型及解引用

char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。
那指针类型的意义是什么?
我们看下面一个代码:
上面代码运行发现: 指针的类型决定了指针加减1操作的时候,跳过了几个字节,决定了指针的步长。char*类型的指针加1跳过一个字节,而int*类型的指针加1跳过了4个字节。
下面我们在看一个代码:

当我们调试过程中发现指针解引用操作时,对于int*类型的指针可以访问四个字节,而对于char*的指针的解引用就只能访问一个字节。
总结:指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
3.野指针
造成野指针的原因有:指针未初始化,指针的越界访问,指针指向的空间释放。
那如何避免野指针呢?
(1).指针初始化;
(2).小心指针越界访问;
(3).指针指向空间释放即使置为NULL;
(4).避免返回局部变量的地址;
(5).指针使用之前检查有效性;
4.指针运算
这里我们只要知道指针与指针之间可以加减运算;指针减去指针得到的是指针和指针之间元素的个数,但注意不是所有指针都能相减,只有指向同一块空间的2个指针才能相减。
下面我们利用指针减去指针求一个字符串的长度:
5.二级指针
指针变量也是变量,是变量就有地址,那么指针变量的地址存放在那里呢?
这就是二级指针。
int  a=10;
int* pa=&a;
int** ppa=&pa;这里ppa 就是二级指针,下面我们画图理解一下二级指针:
6.字符指针
列如
cahr* p="abcdef";
这里我们是把字符串首元素a的地址,赋值给了p;
下面看一个代码:
这里为什么p1==p2,而arr1!=arr2呢,我们可以这么理解,因为字符指针所指向的数据相同,存放在只读存储区里;p1和p2分别指向这块区域;
而arr1和arr2都是单独分别开辟了各自空间来存储,首元素地址是不一样的。
7.指针数组
是数组,用来存放指针的数组;
列如:int* arr2[6];存放整型指针的数组
         cahr* aa3[5];存放字符指针的数组;
指针数组可以拟合二维数组:

 8.数组指针

指向数组的指针;

列如:int (*p)[10];p就是数组指针,p可以指向一个数组,该数组有10个元素,每个元素是int类型

说到这里,我们就大概知道l:

整型指针是用来存放整型的地址;

字符指针是用来存放字符的地址;

数组指针是用来存放数组的地址的;

用于二维数组传参: 

9.函数指针

也就是指向函数的指针;

10.函数指针数组

把函数和指针放在数组中,其实就是函数指针数组

列如:

int(*pf)(int,int)=Add;//函数指针

int (*arr[4])(int,int)={Add,SUb,Div};//函数指针数组

下面我们写一个简单的计算器:实现加减乘除

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
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 meau()
{
    printf("***********************\n");
    printf("****1.Add   2.Sub*******\n");
    printf("****3.Mul   4.Div*******\n");
    printf("****0.exit  ****************\n");
}
int main()
{
    int input = 0;
    int x = 0;
    int y = 0;
    int ret = 0;
    int (*pfarr[5])(int, int) = { 0,Add,Sub,Mul,Div };
    do
    {
        meau();
        printf("请输入input:");
        scanf("%d", &input);
        if (input == 0)
        {
            printf("退出计算器");
        }
        else if (input >= 1 && input <= 4)
        {
            printf("请输入两个操作数");
            scanf("%d %d", &x, &y);
            ret = pfarr[input](x, y);
            printf("%d\n", ret);
        }
        else
        {
            printf("选择错误");
        }


    } while (input);
    return 0;
}

这里我们利用了函数指针数组使得程序大幅简化,而且使得程序更加模块化;这就是函数指针数组的一个运用列子。

10.回调函数

回调函数是通过函数的指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值