由于某些遗留原因,我有将双精度字节转换为无符号字节的代码,我们发现这两个平台之间存在很大差异。缺少做的事情-“不要尝试将有符号的值填充为无符号的值;不要尝试将双精度值填充为整数”,还有其他可以做的事情吗?
unsigned char newR1 = -40.16;
在Windows上,newR1的值为216(正如我们长期以来所期望的那样);但在ARM64上为0。
在Win上反汇编:
00007FF75E388818 cvttsd2si eax,mmword ptr [R]
00007FF75E38881D mov byte ptr [newR1],al
在ARM64上
00007FF6F9E800DC ldr d16,[sp,#0x38 |#0x38 ]
00007FF6F9E800E0 fcvtzu w8,d16
00007FF6F9E800E4 uxtb w8,w8
00007FF6F9E800E8 strb w8,[sp,#0x43 |#0x43 ]
也将尝试这些方法,但只希望有其他意见
unsigned char newR1 = -40.16;
unsigned char newR2 = (int)-40.16;
unsigned char newR3 = (unsigned char)-40.16;
unsigned char newR4 = static_cast<int>(-40.16);
或者可能是
int i = -40.16;
unsigned char c = i;
答案 0 :(得分:4)
C标准所说的(C ++中有类似的文字):
当实数浮点型的有限值转换为整数时 _Bool以外的其他类型,则小数部分将被舍弃(即 值将被截断为零)。如果整数部分的值 不能用整数类型表示,行为是不确定的。
因此,从double
到unsigned char
的一次转换中,从-40.16中获得216已经是UB了。实际上,在这种情况下得到任何结果就是UB。这就是为什么编译器可以自由生成任何东西,而不是您想要的216。
您可能要进行两次强制转换:
(unsigned char)(int)-40.16
同样,第一个(转换为int的)类型仍然受我引用的上述限制。