Bootstrap

【C语言】int *p[ ] 与 int (*p)[ ] 的区分辨析


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C语言


在这里插入图片描述


💯前言

  • C语言系统编程领域的重要语言之一,其中指针的灵活性和强大功能是它的核心之一。指针的灵活性使得它非常强大,但也因此给初学者带来了一些困扰。
    特别是在理解数组和指针结合使用的情况时,如 int *p[10]int (*p)[10],我们常常感到困惑。本文将深入分析这两种声明之间的差异,帮助您从基础到深入理解指针数组指向数组的指针之间的区别。
    C语言
    在这里插入图片描述

💯基本概念:数组与指针

在这里插入图片描述
在进入具体的分析之前,我们首先需要了解一些基本的概念,包括数组和指针。

  1. 数组:数组是一个连续存储相同类型元素的集合。数组的声明需要指定元素类型和元素数量,数组在内存中的存储是连续的,这意味着数组内的每个元素在内存中占据着紧邻的位置。

    • 例如:int arr[5]声明了一个包含5个int类型元素的数组。
  2. 指针:指针是一个存储内存地址的变量。通过指针,我们可以间接地访问存储在内存中的数据。

    • 例如:int *ptr声明了一个指向int类型数据的指针。

指针和数组的结合往往能提供非常强大的操作方式,比如指向数组的指针和指针数组都可以实现非常灵活的数据操作,但是它们的用途和实现方式是不同的。
在这里插入图片描述

💯理解 int *p[10]int (*p)[10]

这两个声明分别有不同的含义,且应用场景也有很大差异。接下来,我们分别对这两种声明进行详细解释。
在这里插入图片描述

1. int *p[10]:存放指针的数组

  • 声明解释int *p[10]是一个“指针数组”。

    • p是一个包含10个元素的数组,其中每个元素都是一个int类型的指针。
    • 换句话说,p是一个数组,数组中的每个元素可以存储一个指向int类型变量的地址。
  • 内存结构:在内存中,这个声明表示有一个包含10个元素的数组,这些元素都是指针,因此每个元素存储的都是某个int变量的地址,而不是int本身。

  • 应用场景:指针数组可以用来处理多个变量指针,比如用来保存多个字符串的首地址。在 C 语言中,字符串数组的实现方式往往就是通过一个指向字符的指针数组来实现的。

    代码示例

    int a = 10, b = 20, c = 30;
    int *p[3];
    p[0] = &a;
    p[1] = &b;
    p[2] = &c;
    
    for (int i = 0; i < 3; i++) {
        printf("%d\n", *p[i]);
    }
    

    在上面的代码中,p是一个指针数组,数组的每个元素都是一个指向整数的指针。p[0]指向ap[1]指向bp[2]指向c,通过*p[i]可以访问每个整数的值。
    在这里插入图片描述

2. int (*p)[10]:指向数组的指针

在这里插入图片描述

  • 声明解释int (*p)[10]是一个“指向数组的指针”。

    • p是一个指针,指向一个包含10个int类型元素的数组。
    • 这里的括号改变了优先级,首先将p声明为一个指针,然后说明这个指针指向一个大小为10的int数组。
  • 内存结构:在内存中,p本身是一个指针,它指向某个数组,这个数组包含10个int类型的元素。

  • 应用场景:指向数组的指针通常用于函数参数,特别是当需要传递一个二维数组给函数时,这种方式非常有用。通过指向数组的指针,可以方便地操作整个数组而不是单个元素。

    代码示例

    int arr[10];
    int (*p)[10] = &arr;
    
    for (int i = 0; i < 10; i++) {
        (*p)[i] = i * 10;
    }
    
    for (int i = 0; i < 10; i++) {
        printf("%d\n", (*p)[i]);
    }
    

    在这个代码中,p是一个指向数组的指针,它指向数组arr。通过(*p)[i]可以对数组的元素进行赋值和访问。
    在这里插入图片描述

💯如何区分这两种声明

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
为了方便理解和区分这两种声明,可以遵循以下规则:

  1. 观察括号的位置

    • int *p[10]中,*紧跟在p之后,说明p是一个数组,每个元素是一个指针。
    • int (*p)[10]中,p被括号括起来,意味着p首先是一个指针,然后指向一个数组。
  2. 理解优先级

    • 数组下标符号[]的优先级高于*,所以在int *p[10]中,p首先被解释为一个数组,接着数组的元素类型是int *
    • int (*p)[10]中,通过括号改变了优先级,使得p首先是一个指针,然后该指针指向一个数组。
      在这里插入图片描述

💯小结

  • 在这里插入图片描述
    int *p[10]:这是一个包含10个指向int类型变量的指针数组。可以看作是“存储指针的数组”。它通常用于处理多个指针,比如保存多个变量的地址,或者在程序中实现多个字符串的存储。
  • int (*p)[10]:这是一个指向包含10个int类型元素的数组的指针。可以看作是“指向数组的指针”。它常用于函数参数中,特别是在处理多维数组时,可以更加灵活地操作整个数组。

理解这些不同的声明方式对于掌握 C 语言中的指针和数组概念非常重要,因为它们是 C 语言强大功能的基础,也是写出高效代码的重要工具。希望通过本文的详细讲解,您能更好地掌握指针数组指向数组的指针之间的区别,增强对 C 语言指针和数组复杂组合的理解。

#include <stdio.h> void processPointerArray(int *arr[], int size) { printf("Values from pointer array (int *p[]):\n"); for (int i = 0; i < size; i++) { printf("%d\n", *arr[i]); } } int main() { int a = 1, b = 2, c = 3; int *pArr[3]; pArr[0] = &a; pArr[1] = &b; pArr[2] = &c; processPointerArray(pArr, 3); int arr[10]; for (int i = 0; i < 10; i++) { arr[i] = i * 10; } int (*p)[10] = &arr; printf("\nValues from pointer to array (int (*p)[10]):\n"); for (int i = 0; i < 10; i++) { printf("%d\n", (*p)[i]); } return 0; }

在这里插入图片描述


;