欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言之指向一维数组的指针

程序员文章站 2024-02-29 22:56:40
...
int array[5] = {1, 2, 3, 4, 5}; // 定义数组
int *intptr = array; // 定义指向数组元素的指针
int (*arrayptr)[5] = &array; // 定义指向数组的指针

上述三条语句分别定义了数组, 指向数组元素的指针和指向数组的指针. 内存情况如图示:
C语言之指向一维数组的指针

对于指向数组元素的指针很好理解, 但是怎样理解 指向数组的指针呢?

  • 怎样理解指针?
    指针可以认为是一个变量, 该变量标记了一段内存, 这段内存的特点是其中存储了固定类型的数据.
    比如上面的ptr初始时标记了array[0]所在的一段内存单元, 这段内存单元存储的是int类型的数据(因为ptr是int类型的指针). 也可以令 ptr = &array[3] , 这样ptr标记的就是array[3]所占的内存单元, 但是其中存储的仍然必须是int类型.
    考虑结构体的情况:
struct student {
    char name[10];
    int age;
};
student Jane = {"Jane', 18};
student *studentptr = Jane;

studetptr初始时标记的是Jane所占的内存空间, 该内存空间存储的数据必须是struct student类型的.
从上面可以看出, 只要有一段内存, 并且这段内存存储的内容具有固定的类型我们就可以定义一个指向它的指针.

  • 数组是一种类型吗?
    所谓类型, 不过是对内存中数据的解释的约定, 我们将Jane所占的前10个字节中的内容解释为字符, 后4个字节解释为整数, 然后我们就约定约定这14个字节的类型是struct student. 数组 不是一种固定的类型, 但是我们可以将 具有5个int元素的数组 认为是一种类型, 这种类型在内存上的特点是连续存储5个整形数据. 我们自然可以位0x1000到0x1004这段内存定义一个指针.

  • 如何解释语句 int (*arrayptr)[5] = &array?
    *arrayptr 表示arrayptr是一个指针;[5] 表示指针指向的对象的类型是具有五个元素的数组;int 表示该数组的元素是int类型的. array 是一个int [5] 类型的数组, 取它的地址初始化arrayptr. 值得注意的是此时数组名array不再表示数组首元素的地址.

  • 如何通过指向数组的指针访问数组的元素?

    • (*arrayptr)[0] == array[0] 首先arrayptr是指向 int [5] 型数组的指针, 那么解引 *arrayptr 得到一个 int [5] 型数组, 然后自然可以通过下标访问数组的元素了.
    • arrayptr[0][0] == array[0] 想弄清楚这个表达式要明白以下几个问题:
      (1) 二维数组实际上就是元素为一维数组的数组
      (2) 二维数组名可以看做指向其第一个元素(一维数组)的指针
      (3) 在内存中2 x 5的二维数组的存储方式是下图所示:
      C语言之指向一维数组的指针
      (4) 一维数组array可以看做一个1 x 5的二维数组
      现在我们将array看作一个只有一个元素的二维数组, 并且该二维数组的元素是 int [5] 类型的, 显然arrayptr指向了该二维数组的第一个元素(相当于二维数组名) 所以我们可以通过下标运算符 arrayptr[0] 获得二维数组的第一个元素(实际上就是array数组), 然后再次利用下标运算符 arrayptr[0][0] 获取array数组的第一个元素. 注意到无法使用 arrayptr[1]是错误的, 因为该二维数组只有一个元素.
      下面的程序展示了指向一维数组的指针:
// 指向一维数组的指针
#include <stdio.h>

int main()
{
    int array[] = {1, 2, 3, 4, 5};
    int *ptr = array;
    int (*arrayptr)[5] = &array;

    // ptr与arrayptr都是指针类型
    printf("ptr所占字节数: %zu\tarrayptr所占字节数: %zu\n", sizeof(ptr), sizeof(arrayptr));

    // *ptrint类型 *arrayptrint [5]类型
    printf("*ptr所占字节数: %zu\t*arrayptr所占字节数: %zu\n", sizeof(*ptr), sizeof(*arrayptr));

    // 使用指向一维数组的指针访问数组元素
    int sum = 0;
    int product = 1;
    for(int i = 0; i < 5; i++) {
        sum += (*arrayptr)[i];
        product *= arrayptr[0][i];
    }
    printf("一维数组array元素的和是: %d\t乘积是: %d\n", sum, product);

    int matrix[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}
    };

    // 指向一维数组的指针指向二维数组的元素
    arrayptr = matrix;      // 相当于arrayptr = &matrix[0]
    arrayptr[0][0]++;       // 相当于matrix[0][0]++
    printf("matrix[0][0]: %d\n", matrix[0][0]);

    (*(arrayptr + 1))[0]++; // 相当于matrix[1][0]++
    printf("matrix[1][0]: %d\n", matrix[1][0]);

    arrayptr[2][0]++;       // 相当于matrix[2][0]++
    printf("matrix[2][0]: %d\n", matrix[2][0]);

    return 0;
}