【问题标题】:getting error: cannot take the address of an rvalue of type 'int'出现错误:无法获取“int”类型的右值的地址
【发布时间】:2016-05-04 16:04:59
【问题描述】:

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

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
}

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

【问题讨论】:

  • 看不出有什么区别,但在这种情况下是 c
  • 演员表无关紧要。说明问题的较短代码:int x, y; int* p = true ? &x : &y; int* q = &(true ? x : y).
  • @yehudahs 您是否尝试编译为 C 和 C++?那么你可能会看到不同。
  • 实际上,发布的代码都没有编译。 (编译时始终启用所有警告。(对于 gcc,至少使用:-Wall -Wextra -pedantic(我也使用:-Wconversion -std=c99))结果是 5 个警告和一个错误。我怀疑您引用了 error 消息:“左值需要作为一元'&'操作数”,但您的问题提到无法获取右值的地址。所以我对您实际询问的内容有点困惑
  • 发布的代码正在尝试从地址 0 获取值。这(几乎)肯定会导致内存访问错误,从而导致段错误事件。

标签: c gcc ternary-operator conditional-operator addressof


【解决方案1】:

在您的代码中

   ((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,不可能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多