字符串末尾的额外零字符出现在 C++ 中用于范围循环
Posted
技术标签:
【中文标题】字符串末尾的额外零字符出现在 C++ 中用于范围循环【英文标题】:Extra zero char at end of string appears in C++ for range loop 【发布时间】:2020-10-12 14:03:20 【问题描述】:以下代码
#include <iostream>
#include <string>
int main()
std::string s = "abc";
for (char c : s)
std::cout << (int) c << " ";
打印“97 98 99”。
以下代码
#include <iostream>
int main()
for (char c : "abc")
std::cout << (int) c << " ";
打印“97 98 99 0”。
第二个代码中多余的 0 来自哪里?
【问题讨论】:
这是常量字符串中的空终止符。 【参考方案1】:文字"abc"
是const char[4]
类型:最后一个元素是NUL 终止符(值为0)。
在第二个 sn-p 中,NUL 终止符的值被打印出来,因为代码描述了对整个 const char[4]
数组的迭代。
在第一个 sn-p 中,std::string
类的底层迭代器技术将结束迭代器(在短形式 for
循环中无法到达)设置为 NUL 终止符。此行为与s.size()
一致。
【讨论】:
【参考方案2】:在第一个 sn-p 中,您使用 range based loop 迭代字符串。 std::string
类型有 .begin()
和 .end()
迭代器。基于范围的循环使用这些标记范围的开始和结束。
在第二个 sn-p 中,您使用基于范围的循环来迭代 string literal。字符串文字基本上是一个字符数组,末尾有一个额外的隐藏 \0
字符。该字符可转换为整数值0
。因此输出中的额外 0。
【讨论】:
【参考方案3】:C++ 有两种不同属性的字符串:
C 字符串和字符串文字
它们是固定大小的空终止字符数组(最大大小在编译时确定)。 "abc"
称为string literal,您可以将其视为包含 'a', 'b', 'c', '\0'
的字符数组。您的 range-based for loop 正在遍历数组中的 所有 个字符,包括空终止符。在没有空终止的情况下打印数据的 C 方式是:
char ca[] = "abc";
char *c = ca;
while (*c)
std::cout << (int) *(c++) << " ";
请注意,不建议使用这种老式的原始指针摆弄方式 - 这太容易自取其辱。
C++ 字符串和 C++ 字符串文字
std::string
提供了一个字符串实现,可以处理任意长度的字符串(内存在运行时动态分配)。 C++ 字符串是具有自己的处理长度方式的对象,不需要空终止。 std::string
类提供了迭代器,使我们能够编写类似的循环
std::string s = "abc";
// Traditional loop with iterators:
for (auto i = s.begin(); i != s.end(); i++)
std::cout << (int) *i << " ";
// Range-based for loop:
for (char c : s)
std::cout << (int) c << " ";
C 字符串"abc"
被传递给std::string
的构造函数,该构造函数以其内部格式存储它。
请注意,C++14 也支持C++ string literals:"abc"s
(注意末尾的运算符s
)。在您的示例中,您可以像这样使用它们:
using namespace std::string_literals;
for (char c : "abc"s)
std::cout << (int) c << " ";
【讨论】:
以上是关于字符串末尾的额外零字符出现在 C++ 中用于范围循环的主要内容,如果未能解决你的问题,请参考以下文章