深度理解C语言三——指针的进阶(数组指针,指针数组)


前言

我们前面对指针有了初步的学习,本篇文章我们来对指针进行较为深入的学习。

一、字符指针

在指针的类型中有一种指针类型为字符指针 char* ;
一般情况下我们就是把一个字符的地址放入字符指针中,但我们这里介绍一下另一种用法:

int main()
{
    const char* p = "hello world";//这里是把一个字符串放到指针变量里了吗?
    printf("%c\n", *p);
    return 0;
}

显然是不可能把一个字符串放到指针变量里的,指针变量这里只有四个字节,根本放不下,我们来打印一下看一看到底放的是啥。
在这里插入图片描述
我们这里其实是把字符串首字符的地址给了p,并没有把整个字符串给p,但是如果想打印整个字符串该怎么打印呢?只需要把%c换成%s,*p换成p就可以了,我只需要知道你的起始地址,就能打印出你全部的内容。
在这里插入图片描述

二、数组指针

数组指针是指针?还是数组?
答案是:指针。
我们前面一起学习过:
整形指针: int * p; 能够指向整形数据的指针。
浮点型指针: float * p; 能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
那么数组指针如何定义呢?
解释:

int (*p)[10]    //解释:p先和*结合,说明p是一个指针变量,然后指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

那么数组指针应该怎么用呢?这里我们先知道一个概念:数组的地址
我们&arr取出的是数组的地址,注意:数组的地址数组首元素的地址意义是不一样的,但他们在数值上是一样的。我们来看一段代码。
在这里插入图片描述

我们可以看出,两个地址数值上是相等的,但是我们分别给这两个地址+1,结果却不一样。&arr+1是向后跳过一个数组,这个数组10个元素,就是向后跳过40个字节。&arr[0]+1是向后跳过一个元素,就是向后跳过四个字节。讲到这里我们就理解了数组的地址的意思了。数组指针存放的是数组的地址,即&arr
我们再来看一下数组指针怎么用。我们举个例子用数组指针来打印数组中的元素。请看下面代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> 
void printf1(int (*p)[5]) {              2.实参传过来整个数组的地址,形参用数组指针来接收。
    for (int i = 0; i <= 4; i++)
    {
        printf("%d ", *(*p + i));        3.*p拿到整个数组,即数组名,即数组首元素地址,(*p+i)拿到数组每个元素的地址,再*(*p + i)拿到数组的每个元素。

    }
}
int main()
{
    int arr[5] = { 0,1,2,3,4,};
    printf1(&arr);                  1.我们把整个数组的元素传进去
 return 0; 
}

我们可以发现,这样做虽然用到了数组指针,但这个算法很麻烦。我们完全没有必要用这种方式来打印数组中的元素,所以数组指针很少用在一维数组中,这里只是通过这个例子来学习理解
数组指针的用法。
我们再来用二维数组举例来学习一下数组指针的用法。还是用打印数组的元素来举例
注意:二维数组的数组名表示首元素地址时表示的是第一行的地址。

#include <stdio.h>
void printf1(int (*p)[2]) {             //2.用数组指针来接受
    for (int i = 0; i <= 1; i++)
    {
        for(int j=0;j<=1;j++)
        {
            printf("%d ", *(*(p+i)+j));    //3.p+i相当于指向第i行,*(p+i)相当于拿到了第i行的数组名,*(p+i)+j相当于指向第i行第j列的某个元素,也就是找到了它的地址。 *(*(p+i)+j)相当于通过它的地址找到了第i行第j列的某个元素
        }
    }
}
int main()
{
    int arr[2][2] = { 0,1,2,3,};     
    printf1(&arr);                  //1.传过去整个数组的地址
    return 0;
}

这里重点理解学习一下数组指针是如何使用的。这里只是通过这个例子来学习理解数组指针的用法。

三、指针数组

先看一下下面这三个

int arr[10]={0};     //存放整形数据的数组
char arr[10]={0};    //存放字符数据的数组
float arr[10]={0};   //存放浮点型数据的数组

那么指针数组就是一个存放指针的数组。(指针存放的是地址,而指针本身也要存放起来。)

int* arr1[10]; //整形指针的数组
char *arr2[4]; //字符指针的数组
char **arr3[5];//二级字符指针的数组

这个具体怎么用呢?请看下面代码:

int main()
{
    int a = 2;
    int b = 3;
    int* p1 = &a;
    int* p2 = &b;
    int* arr[2] = { p1,p2, };
    for (int i = 0; i <= 1; i++)
    {
        printf("%d ", * (arr[i]);     //arr[i]拿到地址,再解引用拿到元素 
    }
    return 0;
}

模拟二维数组

我们还可以用这个来模拟一个二维数组,请看代码:

#include <stdio.h>
int main()
{
    int arr1[3] = { 0,1,2 };
    int arr2[3] = { 3,4,5 };
    int arr3[3] = { 6,7,8 };
    int* arr[3] = { arr1,arr2,arr3};     //数组名表示首元素地址,所以可以放进指针数组
    for (int i = 0; i <= 2; i++)
    {
        for (int j = 0; j <= 2; j++)
        {
            printf("%d", *(arr[i] + j));   //arr[i]拿到第i个数组的首元素地址,+j指向第i个数组中的第j个元素,再解引用表示通过地址找到了这个元素。
        }
        printf("\n");
    }
    return 0;
}

运行结果为:
在这里插入图片描述
这样我们就模拟出了一个3行3列的二维数组。

总结

本篇文章学习了指针的一些较为深的一些知识,希望大家多去理解和学习。由于指针的内容较多,下篇文章继续来学习指针的进阶,本篇文章就先学习到这里。
本篇文章内容结束,感谢大家观看。如果意见或建议,可以在评论区留言,您的点赞是我更新的动力。我们下篇文章再见。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT牛爷爷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值