深度理解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列的二维数组。


总结


本篇文章学习了指针的一些较为深的一些知识,希望大家多去理解和学习。由于指针的内容较多,下篇文章继续来学习指针的进阶,本篇文章就先学习到这里。

本篇文章内容结束,感谢大家观看。如果意见或建议,可以在评论区留言,您的点赞是我更新的动力。我们下篇文章再见。

目录
相关文章
|
6天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
18 3
|
18天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
44 0
|
5天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
12 2
|
14天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
23 1
|
20天前
|
存储 编译器 C语言
【c语言】数组
本文介绍了数组的基本概念及一维和二维数组的创建、初始化、使用方法及其在内存中的存储形式。一维数组通过下标访问元素,支持初始化和动态输入输出。二维数组则通过行和列的下标访问元素,同样支持初始化和动态输入输出。此外,还简要介绍了C99标准中的变长数组,允许在运行时根据变量创建数组,但不能初始化。
35 6
|
17天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
13 2
|
17天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
17天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
24天前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
23天前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。