我对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
返回auint8_t
并将其传递到的push_back
成员函数中std::string
,该成员函数使用char
-,从而发生隐式转换。char
实际上可以是签名的或未签名的。我不确定签名是否会发生。
我无法(不打算使用双关语)将头缠绕在这里发生的事情以及它是否安全。
将其存储在之前是否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-cast
vsstatic-cast
:cstyle-cast执行(链接)
遇到C样式强制转换表达式时,编译器尝试按以下顺序将其解释为以下强制转换表达式:
a)const_cast <新类型>(表达式);
b)static_cast <new_type>(表达式),带有扩展名:甚至允许无法访问基类的指针(或相反),也可以将指向派生类的指针或引用强制转换为指向明确的基类的指针或引用(反之亦然)此强制转换会忽略私有继承说明符)。同样的方法也适用于将指向成员的指针转换为指向明确非虚拟基础的成员的指针;
c)static_cast(带有扩展名),后跟const_cast;d)reinterpret_cast <新类型>(表达式);
e)reinterpret_cast,后跟> const_cast。即使不能编译,也要选择满足各个转换运算符要求的第一个选择。
因此,对于signed<->unsiged
转化,cstyle-cast
应与相同static_cast
。
对于隐式转换(隐式转换-转换顺序)
隐式转换顺序按以下顺序组成:
- 零个或一个标准转换序列;
- 零个或一个用户定义的转换;
- 零或一个标准转换序列。
,在哪里
标准转换序列按以下顺序组成:
- 下列一组中的零或一转换:左值到右值转换,数组到指针转换以及函数到指针转换;
- 零或一个数字提升或数字转换;
- 零或一个函数指针转换;(自C ++ 17起)4)零或一次资格调整。
而数字转换又是顶部引用的转换。
static_cast
本身使用隐式和用户定义的转换(link)的组合在类型之间进行转换。因此,隐式或显式之间不应有任何区别。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句