isspace必须传unsigned char或EOF,直接传char易因符号扩展导致未定义行为;其仅识别C locale下6个ASCII空白符,不支持Unicode,安全用法需static_cast<unsigned char>。

用 isspace 判断字符是否为空格,但必须传 unsigned char 或 EOF
直接传 char 给 isspace 是常见崩溃源头。因为 char 在某些平台默认有符号(signed),遇到值为 0x80–0xFF 的字节(比如 UTF-8 中文字符的高位字节、或读文件时的原始字节)会转成负数,而 isspace 只接受 0–255 范围内的整数(或 EOF)。传负值进去是未定义行为,可能段错误或返回错误结果。
正确做法是先强转:
char c = ...;
if (isspace(static_cast<unsigned char>(c))) { ... }- 所有标准 C 字符分类函数(
isalpha、isdigit等)都有同样要求 - 别依赖编译器警告——有些编译器默认不报这个
- 如果
c来自std::string或数组索引,尤其容易漏掉转换
isspace 识别的不只是 ASCII 空格
isspace 的行为受当前 C locale 影响,默认 "C" locale 下只认 7 个空白字符:' '、'\f'、'\n'、'\r'、'\t'、'\v'。但它**不识别 Unicode 空格**(如 、 、 ),也不识别全角空格(U+3000)。
- 处理 UTF-8 字符串时,
isspace对多字节编码中的单个字节做判断,毫无意义 - 想支持 Unicode 空格?得用 ICU、Boost.Locale,或手动比对码点(需先解码 UTF-8)
- 跨平台程序若改过 locale(比如调了
setlocale(LC_CTYPE, "")),isspace行为可能突变
替代方案:自己写轻量判断更可控
如果只关心 ASCII 空格和常用控制符,自己写一个内联判断反而更安全、更快、无 locale 依赖:
立即学习“C++免费学习笔记(深入)”;
inline bool is_ascii_space(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v';
}- 避免类型转换开销和 locale 查表
- 编译器通常能把它优化成几条比较指令,比
isspace调用还快 - 语义明确:就是这 6 个字符,不多不少
- 注意:不能用于宽字符(
wchar_t)或 UTF-32
从 std::string 或流里读字符时最容易踩坑
比如用 std::getline 读一行后遍历每个 char,或用 std::cin.get() 逐字节读,都容易忘记类型转换:
std::string line = "hello world";
for (char c : line) {
if (isspace(c)) { /* ❌ 危险! */ }
if (isspace(static_cast<unsigned char>(c))) { /* ✅ */ }
}- 哪怕你确定输入只有 ASCII,编译器也不会替你保证运行时字节范围
- 二进制文件、网络包、用户粘贴内容都可能含高位字节
- CI 环境或不同 libc(glibc vs musl)对负值输入的反应可能不同,导致本地测试通过、线上崩溃
实际用 isspace 时,类型转换那一步不是可选项,是必选项;而它能识别的“空白”,远比你直觉中“按空格键出来的”要窄得多。










