c++oding="utf-8" ?>
最稳的方法是直接用 inet_pton 判断,它天然支持所有合法缩写且拒绝非法格式;需预处理截空白、去%后缀、确保c字符串和16字节缓冲区;手动解析须严守冒号数、双冒号唯一性及段长校验三铁律。

直接用 inet_pton 判断最稳,它天然支持所有合法缩写(如 ::1、2001:db8::、::ffff:192.0.2.1),不支持的格式(如 :::、2001::00000)一律返回 0。
为什么不用正则表达式匹配 IPv6 缩写
正则无法可靠处理双冒号展开逻辑和段数归一化。比如 ^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$ 完全不识别 ::;而“完整版”正则在 libstdc++ 或 MSVC 的 std::regex 实现中极易触发灾难性回溯——输个 1:2:3::: 就可能卡死数秒。RFC 4291 规定的压缩规则(最多一个 ::、展开后必须为 8 段、每段 1–4 字符)靠纯文本匹配很难闭环验证。
用 inet_pton 前必须做的三件事
系统 API 不容忍脏输入,漏掉任一预处理都会让合法地址被误判为非法:
- 用
str.find_first_not_of(" \t\n\r")和str.find_last_not_of(" \t\n\r")截掉首尾空白,否则返回 0 - 若字符串含
%(如fe80::1%eth0),需提前截断%及之后全部内容——inet_pton只认纯地址 - 确保传入的是 C 风格字符串:
ip.c_str(),且目标缓冲区大小为sizeof(struct in6_addr)(16 字节)
手动解析缩写时最容易错的三个点
仅当无法调用系统库(如嵌入式裸机环境)才考虑手写。但必须守住三条铁律,缺一不可:
- 统计
:总数:合法 IPv6 字符串中,:必须是 2–7 个(::算两个);::::或a:b:c:d:e:f:g:h:i直接拒绝 - 检查
::出现次数:最多 1 次;若存在,用空段补足至 8 段,再逐段校验长度(1–4)和字符(仅isxdigit允许) - 每段不能全空也不能超长:
2001::00000(末段 5 字符)、2001:::1(连续双冒号)、2001:db8:::8a2e::1(两个::)都非法
真正难的不是识别 ::,而是确认展开后是否恰好 8 段、每段是否在 RFC 范围内。哪怕只漏掉对前导零长度或 % 截断的检查,就可能把 fe80::1%lo 当作非法,或把 2001:db8::00000 当作合法。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











