额外说明及文件下载
有关指针运算的区分.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)