将"uint8_t"(从套接字读取)隐式转换为"char"安全吗

Is it safe to implicitly convert a `uint8_t` (read from a socket) to a `char`?

本文关键字:quot 转换 安全 char 套接字 uint8 读取      更新时间:2023-10-16

我被C++关于无符号到有符号的转换规则弄糊涂了,反之亦然。

我正在从套接字读取数据并将其保存在std::vector<uint8_t>中。然后我需要读一部分(假设它是ASCII数据)并将其保存在std::string中。这就是我正在做的:

for (std::vector<uint8_t>::const_iterator it = payload.begin() + start; it < payload.begin() + end; ++it) {
store_name.push_back(*it);
}

因此,正如您所看到的,*it返回一个uint8_t,并将其传递到std::stringpush_back成员函数中,该函数接受char,因此发生了隐式转换。CCD_ 8实际上可以是有符号的或无符号的。我不确定如果签字会发生什么。

我无法理解(并非双关语)这里发生的事情,以及它是否安全。

store_name.push_back(*it)在将*it的比特模式存储在std::string之前是否改变了它?究竟是什么规则控制着这一点?

我在网上浏览了很多解释类型转换规则的地方,但仍然没有真正打动我。我们将不胜感激。

编辑:作为一种不同的说法,通常,当我们将unsigned强制转换为signed,反之亦然时会发生什么

unsigned char a = 50; // Inside the range of signed char
signed char b = (signed char) a;

b中的比特模式是否需要与a中的比特图案相同?或者比特模式可能会改变?

另外,相反的方向呢:

a = (unsigned char) b;

再一次,位模式是否发生变化?或者,只要值在正确的范围内,无论我们进行多少次有符号无符号转换,都能保证底层的位模式保持不变吗?

它是使用(cstyle cast)static_cast<>的显式强制转换,还是通过赋值的隐式强制转换?

从隐式转换-数字转换/积分转换:

到未签名

如果目标类型是无符号的,则结果值为等于源值模2n的最小无符号值,其中n是用于表示目的地类型的位数。也就是说,取决于目标类型是宽还是窄,有符号整数是符号扩展的[脚注1]或截断的无符号整数整数分别为零扩展或截断。

要签署

如果目标类型已签名,则如果源整数可以用目标类型表示。否则结果是实现定义(直到C++20)的唯一值目标类型等于源值模2n,其中n为用于表示目的地类型的位数。(自C++20)。(请注意,这与带符号整数算术不同溢出,未定义)。

因此,对于范围内的值,不应进行转换。否则,我将其解释为,如果您的机器将值表示为2的补码,则转换为无符号(从C++20也转换为有符号)的位和在C++20之前定义的实现没有变化。(我不知道为什么,但我认为大多数编译器不会更改值,即使它们被允许更改)。


关于cstyle-caststatic-cast:cstyle=cast执行(链接)

遇到C样式转换表达式时,编译器尝试将其解释为以下强制转换表达式,在订单:

a) const_cast<new_type>(表达);

b) static_cast<new_type>(表达式),扩展名为:指针或还允许将对派生类的引用强制转换为指向明确基类的指针或引用(反之亦然)如果基类不可访问(也就是说,此强制转换将忽略私有继承说明符)。同样适用于将指针强制转换为指向明确非虚拟基的成员的成员到指针;

c) static_cast(带扩展名),后跟const_cast;d) interpret_cast<new_type>(表达);

e) interpret_cast紧随其后>通过const_cast。即使无法编译,也会选择满足相应强制转换运算符要求的第一个选项。

因此,对于signed<->unsiged转换,cstyle-cast应该与static_cast相同。


对于隐式转换(隐式转换-转换顺序)

隐式转换序列按以下顺序组成:

  1. 零个或一个标准转换序列
  2. 零个或一个用户定义的转换
  3. 零或一个标准转换序列

,其中

标准转换序列由以下部分组成订单:

  1. 从以下集合进行零或一次转换:左值到右值转换、数组到指针转换和函数到指针转化
  2. 零或一个数字促销或数字转换
  3. 零或一函数指针转换;(由于C++17)4)零或一资格调整

,数字转换再次是顶部引用的转换。

static_cast本身使用隐式转换和用户定义转换(链接)的组合在类型之间进行转换。因此,隐式和显式之间不应该有任何区别。