AIX编译器13.1.3对c ++

时间:2018-08-01 13:37:58

标签: c++ double compiler-optimization aix

我们从char *数组强制转换数据,其功能如下所示:

double getDouble(const char* szData, const size_t dataLength)
{
    double res = 0;
    if(dataLength == 8)
    {
        ub8 doubleData = *(ub8*)(szData);
        doubleData = ntohll(doubleData);
        double* pDoubleData = (double*)(&doubleData);
        res = *pDoubleData;
    }
    return res;
}

ub8的大小为8字节,无符号long long。 并将双值-1.1512299550195975转换为3.6975400899608046。但是输入和输出应该相等(等于-1.1512299550195975)。这种情况仅在AIX中发生。在其他平台上,我们得到正确的结果。

我们在项目中使用优化级别O2。如果我将优化级别用作O1,那么数据将正确转换。 您能为我提供帮助吗,您如何看待,为什么优化级别O1的转换正确,为什么优化级别O2的转换不正确?可能是我应该在编译中关闭aix还是为aix设置一些标志?谢谢。 Aix编译器版本为13.1.3。

我们从二进制文件中以char数组格式获得了double值。我们从Oracle数据库的事务日志中解析数据。例如,oracle将double值写入为'40 0d 94 8f e6 10 3e 93',我们应该在double类型值中将其转换为'-1,1512299550195975'。但是在唯一的aix中,我们得到了“ 3,6975400899608046”错误的值

1 个答案:

答案 0 :(得分:0)

您的实现依赖未定义的行为,尤其是违反了严格别名规则,正如有人评论的那样。

这就是为什么有时它可以工作(没有优化)而有时不起作用的原因。

为避免违反严格别名,您可以使用以下之一:

仅在C语言中使用(不是C ++,更多信息here):

typedef union swap64{
    unsigned long long u64;
    double d64;
}swap64;
swap64 s;
memcpy(s.u64, szData, sizeof(swap64));
s.u64=ntohll(s.u64);

//Following line is UB in C++, but not in C:
return s.d64;

或者没有UB(代码在C ++和C中均有效):

unsigned long long u64;
double d64;

//Most compilers will remove the memcpy calls and replace them by simpler instructions
memcpy(&u64, szData, sizeof(u64));
u64=ntohll(u64);
memcpy(&d64, &u64, sizeof(u64));

return d64;