std::reverse不能直接反转char数组,因其依赖指针范围而数组名退化为指针后丢失长度;需显式传入合法区间如std::reverse(arr, arr + len),且len应为strlen结果而非sizeof,避免越界或破坏'\0'。

std::reverse 为什么不能直接反转 char 数组?
因为 std::reverse 接收的是迭代器(或指针)范围,而裸 char 数组名在传参时会退化为指针,丢失长度信息。如果你只传 arr 和 arr + 1,它只会反转第一个字符;传错长度还会越界读写。
- 必须显式提供起始和结束位置(左闭右开区间),例如
std::reverse(arr, arr + len) -
len要是实际有效字符数(不含末尾'\0'),否则'\0'可能被挪到开头,导致printf或std::cout输出为空 - 如果数组未以
'\0'结尾,std::reverse仍能工作,但它不关心字符串语义,只按你给的指针范围翻转字节
用 std::reverse 反转 C 风格字符串(含 '\0')
典型场景:你有一个以 '\0' 结尾的 char 数组,想原地反转内容但保持结尾仍是 '\0'。这时要排除 '\0',只反转前面部分。
char s[] = "hello"; int len = std::strlen(s); // 得到 5,不包含 '\0' std::reverse(s, s + len); // 翻转前 5 个字节 → "olleh" // s 仍以 '\0' 结尾,可安全用于 C 字符串函数
- 别用
sizeof(s)替代strlen(s)—— 若数组有冗余空间(如char s[10] = "hi"),sizeof返回 10,会导致翻转到未初始化内存 - 若确定数组大小固定且已知(如
char buf[256]),且你填入的字符串始终短于它,仍应先用strlen获取真实长度
手动实现 reverse(避免 STL 依赖或教学需要)
双指针交换是最直观、无额外依赖的方式,也最容易控制边界。
void reverse_cstr(char* s) {
if (!s) return;
int i = 0, j = 0;
while (s[j]) ++j; // 找 '\0',j 即长度
--j; // 回退到最后一个有效字符索引
while (i < j) {
std::swap(s[i++], s[j--]);
}
}
- 注意
j初始化为 0 后通过while(s[j])走到'\0',此时j是'\0'的下标,所以要--j才指向末尾字符 - 如果输入可能为空指针或空字符串(
s[0] == '\0'),循环不会执行,安全 - 这个版本不依赖
<algorithm>或<cstring>(除了std::swap,也可手写临时变量交换)
std::string 比 char 数组更省心?
是的——但前提是你能改用 std::string。它的 reverse 不仅安全,还自动管理内存和长度。
立即学习“C++免费学习笔记(深入)”;
std::string s = "hello"; std::reverse(s.begin(), s.end()); // 直接可用,无需 strlen,无越界风险
- 如果你正在处理 C API 返回的
char*(比如getenv),别直接传给std::reverse——它可能不是 null-terminated,或生命周期不归你管 - 从
char*构造std::string是安全的(前提是它确实以'\0'结尾),之后再反转,但要注意额外拷贝开销 - 嵌入式或性能敏感场景中,坚持用
char数组+手动双指针仍是主流选择
C 风格字符串反转真正容易出问题的地方,从来不是算法本身,而是长度判断——多一位或少一位,就可能把 '\0' 挪走,或者踩进相邻变量内存。动手前,先确认你手里的“长度”到底是谁的长度:是 sizeof 声明大小?是 strlen 实际长度?还是你自己维护的计数?


















