C++20中如何计算unsigned char*的长度?
嘿,我来帮你捋清楚这个问题里的关键点,顺便解决你潜在的内存隐患~
首先回答你最关心的问题:const char*和const unsigned char*指向的单个元素大小是完全一样的——C++标准规定char、signed char和unsigned char的大小都是1字节。不过要区分清楚:指针本身的大小取决于平台(比如64位系统是8字节),但你要的应该是指针指向的字节序列的长度对吧?这个长度只和字节序列本身有关,和指针是char*还是unsigned char*无关。
接下来看你的代码,这里有个很容易踩坑的地方:你用了临时的std::u8string对象,然后直接取它的data()转成unsigned char*。临时对象在当前语句结束后就会被销毁,这时候你的data指针就变成了悬空指针,后续访问它属于未定义行为——这就是你感觉“好像缺了点什么,可能是内存”的原因!
那正确的做法应该是把std::u8string存成一个持久的变量,让它的生命周期覆盖你使用data指针的整个过程:
const std::string s = "...."; std::u8string u8_str(s.begin(), s.end()); // 保存为持久变量,避免临时对象销毁 const unsigned char* data = reinterpret_cast<const unsigned char*>(u8_str.data()); size_t len = u8_str.size(); // 这里用u8_str的size,而不是s的ssize!
这里还要注意:std::ssize(s)返回的是std::string的字符数(也就是char元素的个数),但如果s里包含UTF-8多字节字符(比如中文、emoji),u8_str.size()(字节数)会和std::ssize(s)不一样——你要根据实际需求选择是要字符数还是字节数。
然后说怎么计算unsigned char*的长度,分两种情况:
- 如果你的
unsigned char*指向的是以空字符(值为0)结尾的C风格字节序列,可以用std::strlen(reinterpret_cast<const char*>(data))来获取长度,但前提是序列里确实有终止的'\0',而且中间没有提前出现的0字节。 - 如果是原始字节数据(比如二进制流、非终止的字符串),那必须在获取指针的同时保存长度——裸指针本身没有办法携带长度信息,这也是为什么标准库容器(比如
std::string、std::vector)都会同时管理数据和长度的原因。
再看你的测试代码,循环打印data[k]是没问题的,但要注意如果是UTF-8多字节字符,用%c逐个输出字节可能会显示乱码,如果是ASCII字符就完全ok。另外你代码里的ff_ffv1_enc_rct_search_comp_spv_len看起来是个外部变量,要确保它和你计算的len一致哦。
总结一下:
char*和unsigned char*指向的字节序列长度计算逻辑是一样的,单个元素都是1字节;- 绝对不要用临时字符串的
data(),会导致悬空指针; - 区分清楚字符数和字节数,根据需求选择对应的长度;
- 裸指针必须配合长度使用,除非是带终止符的C风格序列。
备注:内容来源于stack exchange,提问作者Jamaika

