Joh*_*and 19 c++ stdstring c++11
互联网上有几篇帖子暗示你应该使用std::vector<unsigned char>或类似的二进制数据.
但我更倾向于使用std::basic_string变体,因为它提供了许多方便的字符串操作功能.和AFAIK一样,自C++ 11以来,该标准保证了每个已知的C++ 03实现已经完成的工作:std::basic_string将其内容连续存储在内存中.
乍一看,std::basic_string<unsigned char>可能是一个不错的选择.
std::basic_string<unsigned char>但是,我不想使用,因为几乎所有操作系统函数都只接受char*,因此需要进行显式转换.此外,字符串文字是const char*,所以const unsigned char*每次我将字符串文字分配给我的二进制字符串时,我都需要显式强制转换,我也想避免.此外,用于读取和写入文件或网络缓冲区的函数同样接受char*和const char*指针.
这离开了std::string,这基本上是一个typedef std::basic_string<char>.
使用std::string二进制数据的唯一潜在剩余问题(我可以看到)是std::string使用char(可以签名).
char,signed char和,unsigned char是三种不同的类型,char可以是未签名或签名.
因此,当11111111b从std::string:operator[]char 返回实际字节值,并且您想要检查其值时,其值可以是255(如果char是无符号的),也可能是"负面的"(如果char已签名,则取决于您的数字表示).
类似地,如果要将实际字节值显式附加11111111b到a std::string,则只需附加(char) (255)可能是实现定义的(甚至引发信号),如果char已签名且intto char会话导致溢出.
那么,有没有一种安全的解决方法,这又使std::string二元安全?
§3.10/ 15指出:
如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
- [...]
- 与对象的动态类型对应的有符号或无符号类型的类型,
- [...]
- char或unsigned char类型.
如果我理解正确的话,似乎允许使用unsigned char*指针访问和操作a的内容std::string并使其也定义良好.它只是重新解释的位模式作为unsigned char,而没有任何变化或信息丢失,即因为在所有位后者char,signed char以及unsigned char必须使用的值表示.
然后,我可以使用这种unsigned char*内容的解释std::string作为一种手段[0, 255],以一种定义良好且可移植的方式访问和更改该范围内的字节值,而不管其char自身的有效性.
这应该可以解决潜在签名产生的任何问题char.
我的假设和结论是否正确?
此外,在所有实现unsigned char*中,相同位模式(即11111111b或10101010b)的解释是否保证相同?换句话说,标准保证"通过眼睛看unsigned char",相同的位模式总是会导致相同的数值(假设一个字节中的位数是相同的)?
我可以安全地(即,没有任何未定义或实现定义的行为)std::string用于在C++ 11中存储和操作二进制数据吗?
Die*_*ühl 18
转换static_cast<char>(uc),其中uc是类型是unsigned char始终是有效的:根据3.9.1 [basic.fundamental]的表示char,signed char以及unsigned char与相同的char是相同的两个其它类型之一:
声明为字符(char)的对象应足够大,以存储实现的基本字符集的任何成员.如果此组中的字符存储在字符对象中,则该字符对象的整数值等于该字符的单个字符文字形式的值.实现定义char对象是否可以保存负值.字符可以显式声明为unsigned或signed.Plain char,signed char和unsigned char是三种不同的类型,统称为窄字符类型.char,signed char和unsigned char占用相同的存储空间并具有相同的对齐要求(3.11); 也就是说,它们具有相同的对象表示.对于窄字符类型,对象表示的所有位都参与值表示.对于无符号窄字符类型,值表示的所有可能位模式表示数字.这些要求不适用于其他类型.在任何特定实现中,普通char对象可以采用与signed char或unsigned char相同的值; 哪一个是实现定义的.
的范围之外的变换值unsigned char到char意愿,当然,是有问题的,并且可能导致未定义的行为.也就是说,只要你不尝试将有趣的值存储到std::string你就可以了.关于位模式,您可以依靠该n位转换为2 n.在std::string仔细处理时,存储二进制数据应该没有问题.
也就是说,我不买入你的前提:处理二进制数据主要需要处理最好使用unsigned值操作的字节.在没有明确处理的情况下,你需要转换char*并unsigned char*创建方便的错误,同时搞乱char意外使用的少数情况将是沉默的!也就是说,处理unsigned char将防止错误.我也不会购买你得到所有那些好的字符串函数的前提:首先,你通常最好不要使用算法,但二进制数据也不是字符串数据.总结:建议std::vector<unsigned char>不仅仅是凭空而来!故意避免在设计中难以找到陷阱!
唯一有利于使用的温和合理的论据char可能是关于字符串文字的论点,但即便如此也没有用C++ 11引入的用户定义的字符串文字:
#include <cstddef>
unsigned char const* operator""_u (char const* s, size_t)
{
return reinterpret_cast<unsigned char const*>(s);
}
unsigned char const* hello = "hello"_u;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8416 次 |
| 最近记录: |