用指针遍历数组时不能用 ptr == nullptr 判断末尾,因原生数组无内置结束符;越界访问行为未定义;正确做法是显式传长度或设哨兵值。

用指针遍历数组时,不能靠 ptr == nullptr 判断是否到末尾
这是新手最常踩的坑:把指针当链表节点用,以为走到空就停了。C++ 原生数组没有内置结束标记,nullptr 和数组边界毫无关系。一旦越界访问(比如 arr[n]),行为未定义,可能崩溃、读到垃圾值,甚至“看似正常”地跑过去。
正确做法是显式传入长度或使用哨兵值
两种主流方式,选哪个取决于场景:
- 函数参数中额外传入
size_t len,用ptr 判断 —— 最安全、最常用,适用于栈数组、堆数组、<code>std::vector::data()等所有连续内存 - 手动在数组末尾放一个特殊值(如
-1、0、nullptr)作哨兵,循环条件写成*ptr != 0—— 仅限你能控制初始化且数据本身允许该值作终止符的场景(例如 C 风格字符串用'\0')
示例(带长度):
void print_ints(int* arr, size_t len) {
int* ptr = arr;
while (ptr <h3>用 <code>std::end()</code> 或范围 for 更不容易出错</h3><p>如果你操作的是已知大小的数组(如 <code>int arr[5]</code>),编译器能推导长度,直接用标准库工具更可靠:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架"><img
src="https://img.php.cn/upload/skill/000/000/081/178988956499722.jpg" alt="C++ 算法竞赛自动化测试数据生成与校验框架" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架" class="overflowclass">C++ 算法竞赛自动化测试数据生成与校验框架</a>
<p class="overflowclass">根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。</p>
</div>
<a rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
-
std::end(arr)返回指向末尾后一位置的指针,和std::begin(arr)配合用,本质还是基于长度计算,但免去手算错误 - 更推荐范围 for:
for (int x : arr) { ... }—— 底层自动处理边界,连指针都不用暴露
注意:std::end() 对裸指针(如 int* p = new int[10])无效,它只接受数组类型或容器。
警惕指针算术中的隐式类型转换和溢出
写 ptr 时,如果 <code>len 是 int 且为负数,或极大值导致指针运算溢出,结果仍是未定义行为。务必保证:
-
len类型用无符号整型(如size_t) - 调用前验证
arr非空、len合理(尤其来自用户输入或文件读取时) - 避免混合有符号/无符号比较,比如
ptr - arr 中若 <code>ptr - arr是有符号差值,而len是size_t,可能触发隐式转换警告或逻辑翻转
真正麻烦的从来不是“怎么写循环”,而是“谁负责确保 len 正确”——这个责任往往藏在上层接口设计里,容易被忽略。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










