用 char 遍历字符串易越界,因未检查 '\0' 终止符;需手动判断 ptr != '\0',避免多移一位访问非法内存;安全写法是 while (*str != '\0') { ... },未找到返回 nullptr。

用 char* 遍历字符串查找字符时,为什么总越界?
直接用指针遍历 C 风格字符串(char*)找字符,最常踩的坑是没检查结尾空字符 '\0'。C++ 中如果传入的是 std::string 的 c_str(),它返回的指针合法但只在原 std::string 生命周期内有效;若字符串是栈上字面量(如 "hello"),指针可用,但别试图修改。
- 必须手动判断
*ptr != '\0',不能只靠长度——指针本身不带长度信息 - 避免写成
while (*ptr) { ... ptr++; }后多移一位,导致访问'\0'后内存(未定义行为) - 查不到时要返回
nullptr,而不是继续递增指针或返回非法地址
示例(安全遍历):
const char* find_char(const char* str, char target) {
if (!str) return nullptr;
while (*str != '\0') {
if (*str == target) return str;
++str;
}
return nullptr; // 未找到
}
std::string::find() 和手写指针查找,性能差多少?
对绝大多数场景,std::string::find() 不仅更安全,而且不比裸指针慢——现代标准库实现通常用 SIMD 或内建汇编优化,且避免了手动边界判断开销。只有在极端性能敏感、已知字符串极短(
-
std::string::find('a')返回size_t(不是指针),查不到时是std::string::npos - 若后续需要指针(比如修改该位置字符),可转成
&s[found_index],但注意s不能是 const - 不要用
find()结果直接做算术(如ptr + 1),它返回的是偏移量,不是地址
在 std::string 上用指针操作,哪些情况会崩溃?
把 std::string 当 C 风格字符串用指针操作,崩溃往往发生在“以为安全”的地方:
- 调用
data()或c_str()后,又调用了非 const 成员函数(如push_back()、+=、resize()),导致内部缓冲区重分配,原指针失效 - 对
const std::string&取data()后,用const_cast强转并写入——即使编译通过,也可能触发写时复制或段错误 - 用
&s[0]获取指针,但s.empty()为 true,此时&s[0]未定义(C++11 起要求非空)
安全做法:只读场景优先用 c_str();需修改且确定不重分配,先 reserve() 再取 &s[0],并确保全程不触发扩容。
查找多个相同字符时,指针方式怎么避免重复扫描?
如果要找所有匹配位置,用指针比用 find() 更直观——每次找到后从下一个位置继续,不用反复计算偏移。
- 起始指针设为
str,每次找到后更新为found_ptr + 1,而非重置为开头 - 注意
found_ptr + 1可能等于str + len,此时*(found_ptr + 1)是'\0',循环自然终止 - 若需存储所有位置,建议存
size_t偏移量而非指针,避免生命周期问题
简例:
std::vector<size_t> all_positions(const char* str, char target) {
std::vector<size_t> result;
const char* p = str;
size_t pos = 0;
while (*p != '\0') {
if (*p == target) result.push_back(pos);
++p;
++pos;
}
return result;
}</size_t></size_t>
实际写业务代码时,95% 的情况直接用 std::string::find() 或范围 for 循环就够了;只有当你明确知道字符串布局、控制内存生命周期、且 profiler 确认这里是瓶颈时,才动手写指针逻辑。否则,安全性和可维护性损失远大于那几纳秒。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











