错误:表达式不可赋值三元运算符

4
我有以下的代码,但MPLABX XC8编译器提示出错:

error: expression is not assignable

U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : uart1.oerr = 0;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^

这是相关的代码部分:

typedef union {
    struct {
        bool ferr  : 1;  // FERIF Framing Error
        bool aerr  : 1;  // ABDOVF Error
        bool oerr  : 1;  // RXFOIF Error
        bool ready : 1;  // Data Ready to be read
        uint8_t reserved : 4;
    };
    uint8_t status;
}uart1_status_t;

static volatile uart1_status_t uart1;
当我使用相同的东西时,不会出现错误。
if (U1ERRIRbits.RXFOIF) 
    uart1.oerr = 1;
else 
    uart1.oerr = 0;

不明白为什么?


6
要不使用 uart1.oerr = U1ERRIRbits.RXFOIF? 1:0; 替代? - Blaze
1
尝试使用U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : (uart1.oerr = 0)代替。条件绑定比赋值更强。C运算符优先级 - Scheff's Cat
@Blaze 谢谢你!看起来好多了。 @Scheff 谢谢你的回答! :) - Arda30
这是什么意思?“当我使用时,相同的东西不会出错。” 这根本不是同一件事!三元运算符(像任何运算符一样)作为表达式的一部分使用。表达式不会创建lvalue。在您的替代版本中,您有单独的语句,其中将值分配给lvalue。 - Gerhardh
一般规则:三元运算符并不等同于“if”语句。 - Gerhardh
1
另一个通用规则:避免使用 ?: 直到它真正需要。这并不经常发生。 - Lundin
2个回答

4
U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : uart1.oerr = 0;

被解释为:

(U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : uart1.oerr) = 0;

这是一个试图将0分配给...的语句吗?如果你想使用这样的结构,你需要添加花括号:

U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : (uart1.oerr = 0);

或者更好的做法:
uart1.oerr = U1ERRIRbits.RXFOIF ? 1 : 0;

或者:

uart1.oerr = !!U1ERRIRbits.RXFOIF;

或者:

uart1.oerr = (bool)U1ERRIRbits.RXFOIF;

或者真的只是:
uart1.oerr = U1ERRIRbits.RXFOIF;

由于 uart1.oerr 的类型是 bool,因此对于非零值,该值将被隐式转换为1,对于零值,将被转换为0


2
答案很简单,由于C运算符优先级的原因。
U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : uart1.oerr = 0;

被编译成

(U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : uart1.oerr) = 0;

在C语言中,条件不提供LValue。因此,这是编译器错误。
一个解决方案是使用括号:
U1ERRIRbits.RXFOIF ? uart1.oerr = 1 : (uart1.oerr = 0);

请注意,uart1.oerr = 1 不需要括号,因为 ?: 的作用就像括号一样(三目运算符的特殊性质)。
更简单的解决方案已经在 Kamils answer中提到...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接