这个练习来自菜鸟教程的C语言经典100例系列,是许多初学者系统学习C语言时必经的实战环节。练习33看似简单,却蕴含着指针与数组关系的核心知识点。我在带新人时发现,约60%的初学者在这个练习上会犯典型错误——混淆数组名和指针的用法。
题目要求实现以下功能:
这个练习主要考察三个关键能力:
特别注意:数组名在多数情况下会退化为指向首元素的指针,但sizeof操作时例外
c复制#include <stdio.h>
int main() {
int arr[] = {3, 5, 7, 9, 11}; // 初始化数组
int *ptr = arr; // 指针指向数组首地址
int sum = 0;
int len = sizeof(arr)/sizeof(arr[0]); // 计算数组长度
printf("数组元素及累加过程:\n");
for(int i=0; i<len; i++) {
printf("arr[%d]=%d ", i, *(ptr+i));
sum += *(ptr+i);
printf("当前sum=%d\n", sum);
}
printf("\n最终结果:sum=%d\n", sum);
return 0;
}
数组长度计算技巧:
c复制sizeof(arr)/sizeof(arr[0])
这种方法可以自动适应不同数据类型的数组
指针遍历的两种等效写法:
*(ptr+i)ptr[i]错误:int *ptr = &arr;
int *ptr = arr;错误:用指针直接做边界判断
c复制while(*ptr != NULL) // 危险!
错误:错误计算数组长度
c复制int len = sizeof(ptr); // 得到的是指针大小
打印指针值观察变化:
c复制printf("ptr地址:%p 值:%d\n", (void*)ptr, *ptr);
使用调试器观察:
x/5wd ptr命令查看内存watch sum监控变量变化ptr+1实际增加的字节数取决于数据类型:
对于二维数组int arr[3][4]:
*(*(arr+i)+j) 等价于 arr[i][j]测试环境:i7-11800H,gcc 9.4.0
| 访问方式 | 10^7次操作耗时(ms) |
|---|---|
| 数组下标 | 28.7 |
| 指针运算 | 26.4 |
| 指针自增 | 25.9 |
c复制int *end = ptr + len;
for(; ptr<end; ptr++) {
sum += *ptr;
}
边界检查的三种方案:
指针使用的安全规范:
现代C的替代方案:
c复制// C11引入的数组视图
#include <stddef.h>
typedef struct {
int *data;
size_t size;
} IntArrayView;
在实际项目中,我建议将这类基础操作封装成安全的工具函数。比如创建一个带边界检查的数组求和函数:
c复制int safe_array_sum(const int *arr, size_t len) {
if(arr == NULL || len == 0) return 0;
int sum = 0;
const int *end = arr + len;
while(arr < end) {
sum += *arr++;
}
return sum;
}
这种写法既保持了指针运算的效率,又增加了安全性检查。在团队协作中,建立这样的编程规范可以显著减少指针相关的内存错误。