代码之家  ›  专栏  ›  技术社区  ›  Amit

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

  •  0
  • Amit  · 技术社区  · 7 年前

    出于某些遗留原因,我有一段将双精度字节转换为无符号字节的代码,我们看到了这两种平台之间的巨大差异。简而言之——“不要尝试将有符号的值填充到无符号的值中;不要尝试将双精度的值填充到整数中”,还有什么可以做的吗?

    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 回复  |  直到 7 年前
        1
  •  4
  •   Alexey Frunze    7 年前

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

    除_Bool之外的类型,小数部分被丢弃(即 值向零截断)。如果积分部分的值 无法用整数类型表示,行为未定义。

    所以,从-40.16中得到216,从 double unsigned char 已经是UB了。事实上,在这种情况下得到任何结果都是错误的。这就是为什么编译器可以自由生成任何东西,而不是您想要的216。

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

    (unsigned char)(int)-40.16
    

    同样,第一次转换(到int)仍然受到我引用的上述限制。