有符号双精度到无符号字节:ARM64与Win64

时间:2019-03-08 04:25:58

标签: c++ arm

由于某些遗留原因,我有将双精度字节转换为无符号字节的代码,我们发现这两个平台之间存在很大差异。缺少做的事情-“不要尝试将有符号的值填充为无符号的值;不要尝试将双精度值填充为整数”,还有其他可以做的事情吗?

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;

1 个答案:

答案 0 :(得分:4)

C标准所说的(C ++中有类似的文字):

  

当实数浮点型的有限值转换为整数时   _Bool以外的其他类型,则小数部分将被舍弃(即   值将被截断为零)。如果整数部分的值   不能用整数类型表示,行为是不确定的。

因此,从doubleunsigned char的一次转换中,从-40.16中获得216已经是UB了。实际上,在这种情况下得到任何结果就是UB。这就是为什么编译器可以自由生成任何东西,而不是您想要的216。

您可能要进行两次强制转换:

(unsigned char)(int)-40.16

同样,第一个(转换为int的)类型仍然受我引用的上述限制。