为三元运算符内的动态转换生成的代码不正确?

时间:2013-10-16 23:52:16

标签: c type-conversion ternary-operator

我有非常基本的代码来从数组中读取原始数据并将其解释为不同类型的数据。代码中的断言失败了,它看起来像是在C中的三元运算符中不正确的重铸。这是针对嵌入式处理器(Analog Devices Tiger Sharc 201)编译的平台。知道这里可能会发生什么吗?我正在联系ADI公司,但我认为总有一个非常聪明的人可以找出可能出错的地方。

#include <assert.h>

typedef union {
    unsigned int uint32;
    float float32;
} c_t;

int main( int argc, char *argv[] )
{   
    unsigned int r;

    int data_type;

    //data is a raw array, could be floats or unsigned int
    unsigned int data[] = {470698344};    

    //cast raw data as mixed union type
    c_t mixed = *(c_t*) data;       

    //interpret all data as unsigned integer
    data_type = 1;

    //this is where cast to float takes place, resulting in loss of precision
    r = data_type ? mixed.uint32 : mixed.float32;

    //also fails, with no union, results in same code
    //r = data_type ? *((unsigned int *)data) : *((float *) data);

    //r = 470698336, loss of precision 
    //due to incorrect cast inside ternary conditional statement at line 23?
    assert(r == 470698344);             

    return 0;
}

2 个答案:

答案 0 :(得分:3)

条件表达式x ? a : b的类型是表达式ab类型的公共类型。常见类型uint32_tfloat是...... float。无论评估两个操作数中的哪一个,其值都将转换为公共类型,这就是条件表达式的值。

您的号码470698344长度为29位,但您的float只能达到24位精度。所以在转换中,精度会丢失。当条件表达式的值分配给r时,这个不太精确的浮点值将被截断为整数,这与470698344不同。

答案 1 :(得分:1)

在此here

上找到了一个很好的参考
  • 如果两个表达式的类型相同,则结果属于该类型。
  • 如果两个表达式都是算术类型或枚举类型,则执行通常的算术转换(包含在Arithmetic Conversions中)以将它们转换为通用类型。
  • 如果两个表达式都是指针类型,或者如果一个是指针类型而另一个是一个计算结果为0的常量表达式,则执行指针转换以将它们转换为公共类型。
  • 如果两个表达式都是引用类型,则执行引用转换以将它们转换为通用类型。
  • 如果两个表达式都是void类型,则常见类型为void。
  • 如果两个表达式都是给定的类类型,则通用类型是该类类型。

不在前面列表中的第二个和第三个操作数的任何组合都是非法的。结果的类型是公共类型,如果第二个和第三个操作数的类型相同且都是l值,则它是一个l值。