C语言之指针详解(2)

简介: 本章重点1. 字符指针2. 数组指针3. 指针数组4. 数组传参和指针传参5. 函数指针6. 函数指针数组7. 指向函数指针数组的指针8. 回调函数9. 指针和数组面试题的解析

数组指针

数组指针的定义

数组指针是指针?还是数组?

答案是:指针

我们已经熟悉:

整形指针: int * pint; 能够指向整形数据的指针

浮点型指针: float * pf; 能够指向浮点型数据的指针

那数组指针应该是:能够指向数组的指针

我们来看代码

#include<stdio.h>
int main()
{
  //数组指针--指向数组的指针--存放数组的地址
  //arr-首元素的地址
  //&arr[0]-首元素的地址
  //&arr-数组的地址
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int(*p)[10] = &arr;//这里涉及到了()优先级
  return 0;
}

50432ec16e624d2e91e5fe755ec0aba4.png

下面代码哪个是数组指针?

int* p1[10];
int(*p2)[10];
//p1, p2分别是什么?
int(*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合

a7327f805b0440b18d213e856a1868d0.png

我们来看下面代码,(*pa)表示这是一个数组指针,数组里面有10个元素,把数组的地址取出来放到pa里面,然后再*解引用操作又得到了原来的那个数组int arr[10],大家觉得这个方法是不是多此一举,我们的数组指针用在二维数组里面会更加合适

#include<stdio.h>
int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int(*pa)[10] = &arr;
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", *(*pa + i));//这里的*pa == arr;
  }
  return 0;
}

4baaf4a91e08478888a9da565e7e10f9.png

我们再来看一下数组指针用于二维数组的情况

#include<stdio.h>
void print1(int arr[3][5], int x, int y)
{
  int i = 0;
  int j = 0;
  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},{2,3,4,5,6},{3,4,5,6,7} };
  print1(arr, 3, 5);
  return 0;
}

6ed2a16c6e7d47b6b211d066ea0f3d5c.png

这是常规操作打印二维数组的情况,数组名传参是可以直接拿一个数组来接收的,代码运行结果我们也可以看到结果正确

下面我们用指针数组来实现,看代码

这个代码是什么意思呢,首先我们知道二维数组的数组名也是首元素的地址,但是他并不是像一维数组里面的数组名一样是首元素的地址,这时我们想到在初始数组那篇博客讲到的把二维数组看成一个一维数组,所以二维数组的数组名就是首元素的地址也就是第一行一维数组的地址,然后后面我们遍历整个二维数组的时候就是第一行的地址加j先遍历第一行的元素,同理,第二行加j遍历第二行的元素,所以,这就是数组指针应用于二维数组的情况,希望大家能够理解

我把代码给大家,对代码的解释也附在代码后面了

#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));
    }
    printf("\n");
  }
}
int main()
{
  int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
  //print1(arr, 3, 5);//arr--二维数组的数组名--数组名(首元素的地址),对于二维数组来说,它的首元素的地址是谁呢?这里我们应该把二维数组想象成一个一维数组,前面数组的讲解已经给大家讲到了,也就是表示二维数组第一行的地址
  print2(arr, 3, 5);
  return 0;
}

6cefdbe3b46a4cae89e69c9c8337a10e.png


当然你也可以写成

p[i][j];
*(p[i] + j));
*(*(p + i) + j));
(*(p + i))[j]);

48cd23bca5104bba9596a09d3d07cbec.png

下面给大家四个代码来判断一下

看代码

int arr[5];----arr是一个5个元素的整型数组

int *parr1[10];----parr1是一个数组,数组有10元素,每个元素的类型是int*,parr1是一个指针数组

int (*parr2)[10];----parr2是一个指针,改指针指向了一个数组(10个元素),每个元素的类型为Int,parr2是一个数组指针

int (*parr3[10])[5];----大家先想一下这是个什么东西,其实parr3是一个数组,有10个元素,每个元素是一个数组指针,这个指针能够指向5个元素的这一个数组,每个元素是Int

本章终,谢谢支持!!!


相关文章
|
1月前
|
存储 C语言
【C语言篇】深入理解指针3(附转移表源码)
【C语言篇】深入理解指针3(附转移表源码)
36 1
|
25天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
45 0
|
23天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
15 2
|
24天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
24天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
30天前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
30天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
30天前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
1月前
|
C语言
C语言指针(3)
C语言指针(3)
11 1
|
1月前
|
C语言
C语言指针(2)
C语言指针(2)
13 1