跳转至

额外说明及文件下载

有关指针运算的区分.md

#include <stdio.h>

int main(void) {
    int a[] = {1, 3, 5}, x = 7, y = 9;
    int *p = NULL;
    p = a;

    printf("%d", *p    );  // p = a,指向 a[0],输出 1。
    printf("%d", *(++p));  // ++p 将指针移动到 a[1],输出 3。
    printf("%d", * ++p );  // ++p 再次将指针移动到 a[2],输出 5。

    总结:++的优先级大于*,*(++p) 和 * ++p 是一样的
    printf("%d", *(p--));  // 先输出当前指针位置(a[2])的值,即 5。然后 p-- 将指针移动回 a[1]。
    printf("%d", * p-- );  // 先输出当前指针位置(a[1])的值,即 3。然后 p-- 将指针移动回 a[0]。
    printf("%d", * p++ );  // 先输出当前指针位置(a[0])的值,即 1。然后 p++ 将指针移动到 a[1]。

    总结:p-- 和 --p 的区别在于:
    p-- 先输出当前指针位置的值,然后将指针移动回前一个位置,
    --p 则先将指针移动回前一个位置,然后输出当前指针位置的值。
    printf("%d", ++(*p));  // p 当前指向 a[1],值为 3,++(*p) 将 a[1] 增加 1,变为 4,输出 4。
    printf("%d", (*p)++);  // 当前 p 仍指向 a[1],值为 4。(*p)++ 输出当前值 4,然后将其增加 1,变为 5

    这里也体现了括号的优先级
    p = &a[2];  // p 指向 a[2],即 5。
    printf("%d, ", *p    );  // 输出当前 *p 的值,即 5。
    printf("%d, ", *(++p));  // ++p 将指针移动到数组范围外(a[3])。访问越界地址会导致 未定义行为。
    p++;
    printf("%d, ", *p    );  // 再次越界,行为依然未定义。
}

首地址的传递.md

C语言不允许直接传递整个数组作为参数(比如 a[3][3]), 它只能传递数组的首地址

传递数组的首地址,使得函数内部可以通过指针直接修改原数组的内容。 如果传递的是数组的副本(如 a[0][0]),则函数修改的是副本,原数组不会发生改变。

那么,如何传递数组的首地址呢? 一维数组二维数组的传递方式有所不同:

以二维数组为例, 以下是几种表示二维数组首地址的方式: 1. a 表示整个二维数组的首地址类型是 int (*)[n],即指向一维数组(长度为 n)的指针。 a 是第 0 行的起始地址(第 0 行第 0 列元素的地址)。 2. &a[0] 表示二维数组第 0 行的地址,类型是 int (*)[n]。 功能实际上等价于 a,也可以说是 a 是 &a[0] 的简略写法。 3. &a[0][0] 表示二维数组第 0 行第 0 列元素的地址,类型是 int。 这是二维数组中首个元素的实际地址。 4. *a[0]** 表示二维数组第 0 行的首地址,类型是int*。 等价于 &a[0][0],可以通过它访问第 0 行的所有元素。

传递首地址时要注意:函数接收的参数类型,或期望的参数类型要与实际传递类型匹配。否则可能会导致函数无法正确访问数组,但编译器是不会报错滴。

如下是接收的参数类型与实际传递不符的错误示范

#include <stdio.h>

// 接受二维数组的参数,类型为指向含有 n 个整数的一维数组的指针
void printMatrix(int (*matrix)[3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]); // 正确访问二维数组
        }
        printf("\n");
    }
}

int main() {
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int *ptr = &a[0][0]; // 获取二维数组的首地址(类型为 int *)

    // 错误:函数期望的是 int (*)[3] 类型,但传递了 int * 类型
    printMatrix(ptr, 2); // 编译不会报错,但运行时行为不正确

    return 0;
}

函数期望 matrix[i][j] 的访问会偏移 i * 3 + j, 但传递的 int * 指针没有这种结构,运行时可能错误地访问到不正确的内存位置。

同样地,在第19题中,使用scores[0] 和 &scores[0][0],虽然二者的类型相同(均为int *),但实际上,使用scores[0]是错误的, 这就是函数期望的参数类型与实际传递类型不匹配的情况。


怎么匹配?

int (*)[n]类型对应的形式参数为 void function(int *(arr)[N]) N为确定的数,不能省略

int *类型对应对应的形式参数为 void function(int *arr)


文件列表