std::hex不能直接转换字符串,需逐字节处理:字符串转hex用std::hex+setw(2)+setfill(‘0’);hex转字节数组需偶数长度、每两字符解析,推荐c++17的std::from_chars(无异常、零分配),注意其不支持前缀和空格。

std::hex 不能直接转字符串,得自己写解析逻辑
用 std::hex 配合 std::Stringstream 只能格式化整数,对字符串的每个字节做十六进制输出或输入时,它不自动处理字节边界和大小写校验。常见错误是传入一个 "FF0A" 字符串,期望 std::stringstream >> std::hex >> int 就能还原出两个字节,结果溢出或只读到第一个字节。
- 字符串转十六进制(如
"hello"→"68656c6c6f"):必须逐字节取unsigned char,再用std::hex+std::setw(2)+std::setfill('0')格式化 - 十六进制字符串转回字节数组(如
"68656c6c6f"→{0x68,0x65,0x6c,0x6c,0x6f}):必须确保长度为偶数,每两个字符组成一个字节,用std::stoi(..., NULLptr, 16)或更安全的std::from_chars(C++17)解析 - 忽略大小写?
std::stoi支持,但std::from_chars不区分大小写,无需预处理;若手写解析,别忘了std::tolower或查表容错
用 std::from_chars 解析十六进制最稳,但要注意 C++17 起才有
std::from_chars 是目前 C++ 中唯一不依赖流、不抛异常、不分配内存的解析方式,适合高频封包场景。但它不接受带前缀(如 "0xFF")的字符串,也不跳过空格——你给什么它就解析什么,越界或非法字符会直接返回 std::errc::invalid_argument。
- 输入必须是纯十六进制字符(
'0'–'9','a'–'f','A'–'F'),长度必须为偶数,否则后半字节会错位 - 示例:解析两个字符
"a3"到unsigned char:unsigned char byte; auto res = std::from_chars(str.data(), str.data() + 2, byte, 16);注意
byte必须是整型(int或更大),再强转,因为std::from_chars没有unsigned char重载 - 旧项目还在用 C++11/14?老实用
std::stoi(str.substr(i,2), nullptr, 16),但记得加try/catch,且substr有拷贝开销
封包时字节序不显式处理,但 hex 字符串隐含大端
十六进制字符串本身是文本表示,没有字节序概念。但你在把二进制数据(比如 uint32_t val = 0x12345678)转成 hex 字符串时,如果先按小端存入数组再转,得到的是 "78563412";如果按内存原样逐字节(从低地址到高地址)转,其实还是大端视觉顺序——因为人类读 hex 字符串默认左高右低,而内存里低地址存的是 LSB。
- 网络封包要求大端(network byte order)?那你要先用
htonl/htons转换整数,再把结果 reinterpret_cast 成字节数组去转 hex,而不是直接对原始变量取地址 - 调试时用
printf("%02x", buf[i])打印字节流,顺序就是内存从低地址到高地址,对应 hex 字符串从左到右,这就是你该看到的“标准”顺序 - 别在 hex 字符串上做字节序翻转——那是对二进制数据的操作,字符串只是它的编码快照