std::string::size()和length()返回字节数而非Unicode字符数,如"你好"在UTF-8下返回6;C风格字符串需用strlen()但不支持嵌入\0;wstring::size()返回wchar_t个数,字节数需乘sizeof(wchar_t);获取真实字符数须用utf8cpp或ICU。

std::string::size() 和 std::string::length() 返回字节长度
在 C++ 中,std::string 是以 char 为单位的字节序列容器,其 size() 和 length() 成员函数返回的是底层存储的字节数,不是 Unicode 字符数。这适用于 ASCII、UTF-8 编码的字符串(只要你不手动混入多字节序列以外的逻辑),也适用于任意二进制数据。
常见错误是误以为它返回“字符个数”——尤其在处理含中文的 UTF-8 字符串时:一个汉字占 3 字节,size() 就返回 3,不是 1。
-
std::string s = "你好";→s.size()是 6(UTF-8 下每个汉字 3 字节) -
std::string s = "abc";→s.size()是 3 -
std::string s = "a\0b";→s.size()是 3(std::string允许嵌入\0,不以此截断)
C 风格字符串要用 strlen(),但注意空终止和类型安全
对 C 风格字符串(即 const char*),必须用 strlen() 计算字节长度,它从首地址开始计数直到遇到第一个 \0。这意味着它无法处理含中间 \0 的数据,且不检查缓冲区边界。
容易踩的坑:
立即学习“C++免费学习笔记(深入)”;
- 传入未以
\0结尾的char*→ 行为未定义(可能越界读) - 传入
std::string::c_str()是安全的,因为保证以\0结尾;但传入&s[0](无结尾符保证)则不安全 -
strlen()返回size_t,与int混用可能引发隐式转换警告或截断(尤其在 64 位系统上)
宽字符串(std::wstring)不能直接用 size() 算 UTF-16/UTF-32 字节数
std::wstring 的 size() 返回的是 wchar_t 的个数,不是字节数。而 wchar_t 大小平台相关(Windows 通常是 2 字节,Linux/macOS 通常是 4 字节),所以字节数得显式计算:
- Windows(
sizeof(wchar_t) == 2):wstr.size() * 2 - Linux/macOS(
sizeof(wchar_t) == 4):wstr.size() * 4 - 更可移植的做法:
wstr.size() * sizeof(wchar_t)
注意:这仍是编码单元数 × 字节大小,不代表 Unicode 码点数(如代理对在 UTF-16 中占 2 个 wchar_t)。
需要真正 Unicode 字符数?别依赖 size(),得用 ICU 或 utf8cpp
如果业务逻辑真的需要“用户感知的字符数”(比如限制输入框显示宽度、光标移动步长),std::string::size() 完全不可靠。UTF-8 中一个 emoji 可能占 2~4 字节,一个带变音符号的字母可能是多个码点组合。
此时必须解析 UTF-8 序列:
- 轻量方案:用
utf8cpp库的utf8::distance() - 工业级方案:ICU 的
u_strCountChar32() - 手写解析极易出错(如忽略过长序列、无效 continuation byte),不建议
字节长度 ≠ 字符长度,这个区分在日志、协议解析、内存拷贝等底层场景里很关键;但在 UI 文本渲染、编辑器光标定位等高层场景里,硬套 size() 会立刻暴露问题。


















