首页...指针与数组的关系及操作技巧
C语言程序设计第十二章 指针与数组/第二节

指针与数组的关系及操作技巧

2026-03-24

第十二章 指针与数组

第二节 指针与数组的关系及操作技巧

概述

本节将深入探讨C语言中指针与数组之间的紧密联系及其操作技巧。通过本节学习,考生将理解指针和数组的本质区别与联系,掌握如何利用指针高效操作数组,理解数组名的指针性质,学会多维数组指针的使用,并能熟练应用相关知识解决实际问题。掌握本节内容是全国计算机等级考试二级C语言程序设计的重要知识点,有助于提升程序设计能力和理解底层内存操作。

核心概念

  • 数组(Array):一组具有相同类型的元素按连续内存空间排列的数据集合。数组名表示数组首元素的地址。
  • 指针(Pointer):存储变量的内存地址的变量,指针类型决定它指向的数据类型。
  • 数组名作为指针:数组名本质上是首元素的地址,常用作指针。
  • 指针运算:指针可以进行加减操作,移动到相邻元素的地址。
  • 多维数组指针:指向多维数组中某一行或某一元素的指针。

原理分析

C语言中,数组和指针关系密切但不完全相同。数组名代表数组首元素的地址,但数组本身是一个固定大小的连续内存块,不能被赋值或改变。指针则是一个变量,可以指向任意地址并且可以修改。指针的算术运算以其指向的数据类型大小为单位进行偏移。通过指针访问数组元素,可以灵活实现数组遍历、动态内存访问等功能。

多维数组在内存中也是连续存储的,按行优先(Row-major)方式排列。二维数组的指针可以指向整个二维数组、某一行或某一元素,理解这些指针的类型和访问方式是掌握多维数组操作的关键。

详细内容

1. 数组名与指针的关系

数组名在表达式中通常转换为指向首元素的指针。例如,若int a[5];,则a等价于&a[0]。这意味着可以使用指针运算遍历数组。

但需要注意:

  • 数组名是常量指针,不能被赋值。
  • 指针变量可以赋值、修改。

示例:

int a[3] = {10, 20, 30};
int *p = a; // 等价于 int *p = &a[0];

此时,p指向数组首元素,可以通过p[i]访问元素。

2. 指针访问数组元素的两种方式

访问数组元素有两种常用方式:

  • 使用数组下标:a[i]
  • 使用指针偏移:*(a + i)*(p + i)

这两种方式等价,因a[i]定义为*(a + i)

示例:

printf("%d", a[2]);
printf("%d", *(a + 2));

输出结果相同。

3. 指针运算与数组遍历

指针变量通过加法操作,移动到数组中下一个元素地址。

示例遍历:

for(int i = 0; i < 5; i++) {
    printf("%d ", *(p + i));
}

同时也可用指针递增实现遍历:

for(int *ptr = a; ptr < a + 5; ptr++) {
    printf("%d ", *ptr);
}

此方法体现指针的灵活性。

4. 指针与多维数组

多维数组的指针理解较为复杂。以二维数组int b[3][4];为例:

  • b是指向含4个int元素数组的指针,即int (*)[4]
  • b[0]是首行数组,类型为int[4]
  • &b[0][0]是指向首元素的int*

访问元素的方式:

  • b[i][j]
  • *(*(b + i) + j)

示例:

printf("%d", b[1][2]);
printf("%d", *(*(b + 1) + 2));

两者结果相同。

5. 指向多维数组的指针定义及应用

定义指针指向二维数组的行:

int (*p)[4] = b; // p指向含4个int的数组

访问元素:

printf("%d", p[2][3]);

此时,p视为二维数组指针,方便传递多维数组参数。

6. 指针与数组参数传递

数组作为函数参数时,实际上传递的是指向首元素的指针。多维数组参数需要明确维度以便计算偏移。

函数声明示例:

void func(int a[], int n); // 一维数组
void func2(int b[][4], int m); // 二维数组,第二维必须明确

函数内部通过指针访问数组元素。

实例分析

实例1:利用指针遍历数组并求和

背景:计算整型数组元素的和。

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *p = arr;
    int sum = 0;
    for(int i = 0; i < 5; i++) {
        sum += *(p + i);
    }
    printf("Sum = %d\n", sum);
    return 0;
}

分析:通过指针p和指针运算访问数组元素,灵活遍历。

结论:指针操作数组简洁且高效。

实例2:二维数组元素访问与修改

背景:修改二维数组中的指定元素。

#include <stdio.h>

int main() {
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    int (*p)[3] = matrix;
    p[1][1] = 55; // 修改第二行第二列元素
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }
    return 0;
}

分析:使用二维数组指针p访问并修改元素。

结论:指针配合多维数组可灵活操作。

实例3:函数中使用指针参数访问数组

背景:编写函数,打印数组内容。

#include <stdio.h>

void printArray(int *arr, int size) {
    for(int i = 0; i < size; i++) {
        printf("%d ", *(arr + i));
    }
    printf("\n");
}

int main() {
    int arr[4] = {10, 20, 30, 40};
    printArray(arr, 4);
    return 0;
}

分析:数组作为参数传递其实是传递指针。

结论:指针参数使函数灵活操作数组。

常见误区

  • 误区1:将数组名当作普通变量赋值

    • 错误:a = p;(数组名不可赋值)
    • 正确:使用指针变量存储地址,数组名本质是常量指针。
  • 误区2:忽视指针类型导致访问错误

    • 指针类型决定指针算术运算的步长。
    • 应确保指针类型与指向数据类型一致。
  • 误区3:多维数组指针声明不正确

    • 二维数组指针应声明为int (*p)[列数],列数必须明确。
  • 误区4:错误使用指针运算导致越界访问

    • 指针移动时需注意边界,避免访问非法内存。
  • 误区5:混淆指针与数组的sizeof

    • sizeof(array)是整个数组大小,sizeof(pointer)是指针大小,两者不同。

应用场景

  • 数组遍历与操作:利用指针遍历数组元素,实现高效访问。
  • 函数参数传递:指针作为函数参数传递数组,节省内存,提升性能。
  • 动态分配内存:通过指针操作动态分配的数组,灵活管理内存。
  • 多维数组处理:图像处理、矩阵计算中使用多维数组指针。
  • 字符串处理:字符串本质是字符数组,指针操作字符串更灵活。

知识拓展

  • 指针与字符串:字符串数组与字符指针的关系。
  • 动态内存分配:结合malloc等函数动态操作数组。
  • 指针数组与数组指针:区别及应用。
  • 指针函数与函数指针:高级指针用法。

总结回顾

本节全面解析了指针与数组的关系,强调了数组名作为指针的本质,介绍了指针访问数组元素的多种方式,详细讲解了多维数组指针的定义与操作。通过典型实例,考生能够理解指针遍历数组、修改数组内容及函数中数组指针参数的应用。掌握指针与数组的正确使用方法,避免常见的误区,是提高C语言程序设计能力的关键。指针与数组的灵活运用是编写高效、可维护程序的重要基础,对全国计算机等级考试二级C语言科目具有重要指导意义。


核心知识点回顾

  • 数组名代表首元素地址,常用作指针。
  • 指针运算以数据类型大小为单位。
  • 通过指针访问和遍历数组元素。
  • 多维数组指针的定义和访问方式。
  • 数组作为函数参数实为指针传递。
  • 注意指针类型匹配,避免非法访问。
  • 区分数组名和指针变量,理解其不可赋值性质。
  • 指针与数组操作在实际编程中的广泛应用。

重点知识点

1

数组名作为指针,表示数组首元素地址

2

指针运算以指向数据类型大小为单位偏移

3

通过指针访问数组元素与使用数组下标等价

4

多维数组指针的定义和元素访问方式

5

数组作为函数参数时实为指针传递

6

指针类型必须与指向数据类型匹配

7

数组名是常量指针,不可赋值

8

指针操作数组提高程序灵活性和效率

9

多维数组按行优先存储,指针访问需考虑维度

10

避免指针越界访问是安全编程关键