11

我尝试用新编译器编译旧代码并得到下一个错误:

error: cannot take the address of an rvalue of type 'int'

这是有 2 行的示例 - 一个编译,另一个给出错误

struct mstct {
    int myfield;
    int myfield2[5];
    int myfield3[5];
};

typedef struct mstct db_data_px;

int foo(int a, int b, int c){

  //the next code compiles successfully.
  unsigned val1 = ((18 == c) ? ((unsigned) & (((db_data_px *) 0)->myfield)) : ((unsigned) & (((db_data_px *) 0)->myfield3[b]))); //successes


  //the next code is failing
  unsigned val2 = (unsigned) & ((18 == c) ? (((db_data_px *) 0)->myfield) : (((db_data_px *) 0)->myfield3[b]));
  return 0; // failing
}

为什么第一行编译,第二行失败?为什么我需要在两个选择表达式中强制转换 (unsigned) & 并且仅在选择表达式被赋值后才强制转换是不够的?

4

1 回答 1

9

在您的代码中

   ((18 == c) ? (((db_data_px *) 0)->myfield) : (((db_data_px *) 0)->myfield3[b]))

是一个不产生左值的条件表达式。

上面的表达式为您提供了一个右值(non-lvaue),您不能对其使用&运算符。

详细说明,引用C11标准,章节 §6.5.3.2,地址和间接运算符

一元运算&符的操作数应该是一个函数指示符、一个 []或一元运算符的结果*,或者是一个左值,它指定一个不是位字段且未使用register存储类说明符声明的对象。

OTOH,对于条件运算符的结果类型,第 6.5.15 章,脚注

条件表达式不会产生左值。

试想一下,&5不可能。

于 2016-01-27T15:49:13.087 回答