gpt4 book ai didi

c++ - 我可以安全地将 std::string 用于 C++11 中的二进制数据吗?

转载 作者:IT老高 更新时间:2023-10-28 21:57:25 48 4
gpt4 key购买 nike

互联网上有几篇帖子建议您应该使用 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 ,它基本上是 std::basic_string<char> 的 typedef .

使用 std::string 唯一可能存在的问题(我可以看到)对于二进制数据是 std::string使用 char (可以签名)。

char , signed char , 和 unsigned char是三种不同的类型,char可以是未签名的或已签名的。

所以,当实际字节值为 11111111bstd::string:operator[] 返回作为 char,如果你想检查它的值,它的值可以是 255 (如果 char 未签名)或者它可能是“负数”(如果 char 已签名,取决于您的数字表示)。

同样,如果您想显式附加实际字节值 11111111bstd::string , 只需附加 (char) (255)如果 char 可能是实现定义的(甚至发出信号)已签署,intchar对话导致溢出。

那么,有没有一种安全的方法来解决这个问题,使 std::string又是二进制安全的?

§3.10/15 规定:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • [...]
  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • [...]
  • a char or unsigned char type.

如果我理解正确的话,它似乎允许使用 unsigned char*访问和操作 std::string 内容的指针并使其也定义明确。它只是重新解释位模式为 unsigned char ,没有任何变化或信息丢失,后者即因为 char 中的所有位, signed char , 和 unsigned char必须用于值表示。

然后我可以使用 unsigned char* std::string的内容解读作为访问和更改 [0, 255] 中的字节值的一种方式范围,以明确定义和可移植的方式,与 char 的符号无关自己。

这应该可以解决由可能已签名的 char 引起的任何问题。 .

我的假设和结论正确吗?

还有,unsigned char*相同位模式的解释(即 11111111b10101010b )保证在所有实现上都相同?换句话说,标准是否保证“通过 unsigned char 的眼睛看”,相同的位模式总是导致相同的数值(假设一个字节中的位数相同)?

我可以因此安全地(即没有任何未定义或实现定义的行为)使用std::string吗?用于在 C++11 中存储和操作二进制数据?

最佳答案

转换 static_cast<char>(uc)在哪里 uc类型为 unsigned char始终有效:根据 3.9.1 [basic.fundamental] char 的表示, signed char , 和 unsigned charchar 相同与其他两种类型之一相同:

Objects declared as characters (char) shall be large enough to store any member of the implementation’s basic character set. If a character from this set is stored in a character object, the integral value of that character object is equal to the value of the single character literal form of that character. It is implementation-defined whether a char object can hold negative values. Characters can be explicitly declared unsigned or signed. Plain char, signed char, and unsigned char are three distinct types, collectively called narrow character types. A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements (3.11); that is, they have the same object representation. For narrow character types, all bits of the object representation participate in the value representation. For unsigned narrow character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types. In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined.

转换 unsigned char 范围之外的值至char当然,这将是有问题的,并可能导致未定义的行为。也就是说,只要您不尝试将有趣的值存储到 std::string你会没事的。关于位模式,您可以依赖 n翻译成 2 n 的位。将二进制数据存储在 std::string 中应该没有问题。小心处理。

也就是说,我不相信你的前提:处理二进制数据主要需要处理最好使用 unsigned 处理的字节。值(value)观。您需要在 char* 之间转换的少数情况和 unsigned char*在弄乱 char 的使用时未明确处理时会产生方便的错误一不小心就会沉默!即处理unsigned char将防止错误。我也不相信您会获得所有这些不错的字符串函数的前提:首先,您通常最好还是使用算法,但二进制数据也是 not 字符串数据。综上所述: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;

关于c++ - 我可以安全地将 std::string 用于 C++11 中的二进制数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19757653/

48 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com