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

简介: 深度理解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天前
|
存储 C语言 C++
【C语言数组】
【C语言数组】
|
5天前
|
存储 编译器 C语言
【C语言】【指针1】指针难?看这个就够了!
【C语言】【指针1】指针难?看这个就够了!
|
5天前
|
C语言
C语言------指针
这篇文章是关于C语言中指针的实训,通过示例代码展示了指针的基本概念、定义、赋值、使用和传递,以及指针运算和指针在函数参数中的应用,如交换两个变量的值和找出两个数中的较小值。
C语言------指针
|
5天前
|
算法 C语言
C语言------数组
这篇文章是关于C语言数组的实训,包括一维数组、二维数组和字符数组的定义、赋值、输入、输出方法,并通过实例代码演示了数组的使用和一些基本算法,如冒泡排序。
C语言------数组
|
17天前
|
存储 编译器 程序员
七:《初学C语言》— 数组
【8月更文挑战第2天】本篇文章详细讲解了一维数组和二维数组的创建、使用和初始化及如何使用sizeof()计算数组中的元素个数。并附带了多个教学源码及代码练习
34 1
七:《初学C语言》— 数组
|
3天前
|
算法 Java
双指针在数组遍历中的应用
文章深入探讨了双指针技术在数组遍历中的应用,通过实战例子详细解释了快慢指针和首尾指针的不同用法,并提供了解决LeetCode相关问题的Java代码实现。
|
3天前
|
存储 搜索推荐 C语言
C语言中的指针函数:深入探索与应用
C语言中的指针函数:深入探索与应用
|
5天前
|
存储 编译器 C语言
【C语言】指针练习题目
【C语言】指针练习题目
|
6天前
|
存储 编译器 C语言
C语言——数组
C语言——数组
|
11天前
|
存储 C语言
C语言(数组)
C语言(数组)
22 6