数组与指针
翻译整理自 cppreference - 数组 与 指针。
1. 一维数组
int arr[5] = {1, 2, 3, 4, 5};
int b[5] = {0}; // 全 0
int c[5] = {1, 2}; // 1,2,0,0,0
int d[] = {1, 2, 3}; // 大小推断为 3
获取长度:
int n = sizeof(arr) / sizeof(arr[0]);2. 多维数组
int m[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
m[1][2] = 99;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
printf("%d ", m[i][j]);3. 指针基础
int x = 10;
int *p = &x; // 取地址
printf("%p\n", (void *)p);
printf("%d\n", *p); // 解引用,10
*p = 20;
printf("%d\n", x); // 20
4. 指针与数组
数组名在表达式中退化为指向首元素的指针:
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // 等价 p = &arr[0]
printf("%d\n", p[2]); // 3
printf("%d\n", *(p + 2));// 3
5. 指针算术
int *p = arr;
p++; // 移动到下一元素(地址 + sizeof(int))
p + 2;
p - 1;
p2 - p; // 元素个数差
6. 字符串与字符指针
char s[] = "hello"; // 数组,可改
char *t = "hello"; // 字符串字面量,**只读**
s[0] = 'H'; // OK
t[0] = 'H'; // UB! 修改只读内存
改字符串用数组,避免用
char *指向字面量后修改。
7. const 与指针
const int *p1; // 指向 const int 的指针,不能 *p1 = ..
int *const p2 = &x; // 指针本身 const,不能 p2 = ..
const int *const p3 = &x; // 都 const
阅读技巧:从右往左读。
8. 指针的指针
int x = 5;
int *p = &x;
int **pp = &p;
**pp = 10;
printf("%d\n", x); // 10
9. 动态分配内存
malloc / calloc / realloc / free:
#include <stdlib.h>
int *arr = malloc(10 * sizeof(int));
if (!arr) { perror("malloc"); exit(1); }
for (int i = 0; i < 10; i++) arr[i] = i;
arr = realloc(arr, 20 * sizeof(int)); // 扩容
free(arr); // 别忘释放
arr = NULL; // 防悬空
calloc 自动清零:
int *z = calloc(10, sizeof(int));10. 函数指针与回调
void apply(int *arr, int n, int (*fn)(int)) {
for (int i = 0; i < n; i++) arr[i] = fn(arr[i]);
}
int dbl(int x) { return x * 2; }
apply(arr, 5, dbl);11. 数组指针 vs 指针数组
int *arr1[10]; // 指针数组:10 个 int*
int (*arr2)[10]; // 数组指针:指向含 10 个 int 的数组
12. 常见陷阱
- 越界访问:
arr[5]当arr只有 5 个元素 - 悬空指针:
free后继续用 - 内存泄漏:分配后忘记
free - 二次释放:同一指针
free两次 - 返回局部变量地址
小结
指针是 C 的灵魂也是危险之源,下一章学习字符串。