C语言之指针数组与数组指针

简介: C语言之指针数组与数组指针

指针数组:

本质依然是数组,只是数组中存放的元素都是指针。就比如好孩子,好只是修饰词,无论他好不好,他都是孩子

#include<stdio.h>
int main()
{
  int arr[10] = { 0 };//整型数组
  char ch[5] = { 0 };//字符数组
  int* pr[4];//存放整形指针的数组----指针数组
  char* pr1[5];//存放字符指针的数组----指针数组
  return 0;
}

现在我们通过一个示例感受一下这个过程:

#include<stdio.h>
int main()
{
  int arr1[] = { 1,2,3,4,5 };
  int arr2[] = { 2,3,4,5,6 };
  int arr3[] = { 3,4,5,6,7 };
  int* parr[] = { arr1,arr2,arr3 };//将数组arr1/arr2/arr3存放到指针数组parr中
  int i;
  for (i = 0; i < 3; i++)//对指针数组中的元素进行访问
  //也就是对arr1/arr2/arr3的首元素地址进行访问
  {
    int j = 0;
    for (j = 0; j < 5; j++)//对每个数组中的元素进行访问
    {
      printf("%d ", *(parr[i]+j));//parr[i]输出指针数组的元素等价于输出每个元素的首地址
      //+j之后会对三个数组中的元素进行访问
    }
    printf("\n");
  }
  return 0;
}

输出结果如下所示:

数组指针:

本质依然是指针,只不过为指向数组的指针,存放数组的地址


那该如何定义呢?首先,回忆我们之前学过的整形指针和字符指针的定义方法

int* p = NULL;//p是整形指针---指向整形的指针--可以存放
  char* pc = NULL;//pc是字符指针---指向字符的指针

其次,我们之前还学过对任意数组有:

int arr[10]={0};
//arr/&arr[0]为首元素地址
//&arr为整个数组的地址

那么数组指针是不是可以这样表示

下面那个是数组指针?

1:int* p1[10];
2:int(*p2)[10];

正确答案是2,那么1为什么不是呢?原因是[]的优先级高于*,对于第一种,p1会优先和[]进行结合,这里的p就成为数组了,但2将p2括起来,强制使p先和进行结合,这里的p是指针。

下面再通过一道题考考你:

如下所示代码中的pa应该怎么进行定义呢?

char* arr[5];
pa = &arr;

采访了一一些同学后,有以下三种答案,那么到底哪种是正确的呢?

A:char(*pa)[5];
B:char* (*pa)[5];
C:char(**pa)[5];

正确答案为同学B的,下面我们来说说该怎么正确定义:

先对代码进行分析:

char* arr[5];//定义字符指针数组,元素个数为5个
pa = &arr;//将数组arr的地址存放到pa中

我们想定义一个数组指针,那么首先得指明pa是一个指针即为pa,又因为上文我们提到,[]的优先级高于,因此我们赶快将*pa括起来,即为(*pa),又因为arr本身是数组,那么指针pa需要指明数组的元素,即为(*pa)[5],最后在最面加上数组的类型,可以类比整形指针的定义方法。


数组名VS&数组名:

数组名代表数组首元素地址,&数组名代表整个数组的地址。

下面我们通过一段代码验证一下:

arr+1跳过的字节长度为一个int,而&arr+1跳过的字节长度为10个int

一维数组与数组指针的结合使用:

举例:

#include<stdio.h>
int main()
{
  int arr[10] = { 2,34,51,2,3,10,9,11,21,0 };
  int(*pa)[10] = &arr;
  int i;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", (*pa)[i]);
    //printf("%d ",*(*pa+i));
    //(*pa)[i],*pa==arr先对指针进行解引用操作,再找数组中的元素
  }
  return 0;
}
2 34 51 2 3 10 9 11 21 0

看到这里,有的小伙伴会觉得干嘛要搞得这么麻烦啊?直接用指针输出就可以了啊

#include<stdio.h>
int main()
{
  int arr[10] = { 2,34,51,2,3,10,9,11,21,0 };
  int* p = arr;
  int i;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", *(p+i));
  }
  return 0;
}

是的,这样确实也能很好的输出,但数组指针的实用性并不体现在一维数组,而是二维及二维以上数组,下面我们通过示例验证:

对于二位数组元素的输出,常规方法:
#include<stdio.h>
void print1(int arr[3][5], int x, int y)//传递数组形式,行,列,参数是数组
{
  int i, j;
  for (i = 0; i < x; i++)
  {
    for (j = 0; j < y; j++)
    {
      printf("%d ", arr[i][j]);
    }
    printf("\n");
  }
}
int main()
{
  int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,0},{0,9,8,7,6} };
  print1(arr, 3, 5);//传递数组名,行,列
  return 0;
}

使用数组指针的方法:
#include<stdio.h>
void print2(int(*p)[5], int x, int y)//参数是指针,传递的为第一行的地址
{
  int i = 0;
  for (i = 0; i < x; i++)
  {
    int j = 0;
    for (j = 0; j < y; j++)
    {
      printf("%d ", *(*(p + i) + j));//*(p+i)找到该二维数组的确定的行,+j之后才能找到每行的每个元素
      //printf("%d ", *(p + i) [j]);
    }
    printf("\n");
  }
}
int main()
{
  int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,0},{0,9,8,7,6} };
  print2(arr, 3, 5);
  return 0;
}

怎么理解二维数组呢?

最后我们通过示例区分一下这几个概念:

int arr[5];//arr是含有5个元素的整型数组
int* parr1[5];//parr1是一个数组,数组有10个元素,每个元素的类型是int*,parr1是指针数组
int(*parr2)[10];//parr2是一个指针,该指针指向了一个数组
         //数组中有10个元素,其类型为int,parr2为数组指针
int(*parr3[10])[5];//parr3是一个数组,该数组有10个元素,每个元素是一个数组指针
           //该数组指针指向的数组有5个元素,每个元素是int


相关文章
|
20天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
74 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
20天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
46 9
|
20天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
40 7
|
20天前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
65 6
|
24天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
45 5
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
105 13
|
24天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
24天前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
82 3
|
25天前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
1月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
52 11