【问题标题】:Compiles as C++ but not C (error: lvalue required as unary '&' operand)编译为 C++ 但不是 C(错误:需要左值作为一元“&”操作数)
【发布时间】:2015-12-30 06:11:45
【问题描述】:

这一行在我使用 C++ 时编译,但不是 C:

gmtime(&(*(time_t *)alloca(sizeof(time_t)) = time(NULL))); //make an lvalue with alloca

我对这种差异感到惊讶。甚至没有针对 C++ 的警告。

当我指定gcc -x c 时,消息是:

playground.cpp:25:8: error: lvalue required as unary '&' operand
 gmtime(&(*(time_t *)alloca(sizeof(time_t)) = time(NULL)));
        ^

这里的& 不只是一个地址运算符吗?为什么它在 C 和 C++ 中不同?

虽然我可以在 C 中使用复合文字,但是否可以修改我的语法以使其在 C 和 C++ 中都可以使用?

【问题讨论】:

  • 另外,区别不在于&,而在于(*(time_t *)alloca(sizeof(time_t)) = time(NULL)) 是否为左值。
  • 另外,为什么不把它写成两行呢? time_t t = time(NULL); gmtime(&t);
  • @immibis 主要是因为我想获取一个临时对象的地址(time_t 值只使用一次)。我发现 C 中的复合文字非常方便,但我不能在 C++ 中使用它。

标签: c++ c compiler-errors lvalue rvalue


【解决方案1】:

在 C11 6.5.16/3 中:

赋值运算符将值存储在左操作数指定的对象中。赋值表达式在赋值后具有左操作数的值,但不是左值

在 C++14 5.17/1 中:

赋值运算符 (=) 和复合赋值运算符都从右到左分组。都需要一个可修改的左值作为其左操作数并返回一个左值引用左操作数。

(早期版本的语言标准在每种情况下都指定了相同的内容)。

由于地址运算符只能对左值进行操作,因此代码在 C++ 中是正确的,但在 C 中是不正确的。


关于“是否可以修改我的语法以使其同时在 C 和 C++ 中工作?”的问题。这不是一个理想的目标;这两种语言是不同的,你应该决定你在写什么。这与尝试坚持在 C 和 Java 中都适用的语法一样有意义。

根据其他人的建议,您可以这样写:

time_t t = time(NULL);
gmtime(&t);

与您的原始代码相比,它具有以下优势:

  • 更简单,因此更易于理解和维护
  • 不依赖非标准的alloca函数
  • 没有潜在的对齐冲突
  • 不使用更多内存,可能使用更少

【讨论】:

  • 我不知道规则背后的基本原理,但我认为最初在 C 中它从来都不是左值(很少有任何理由尝试修改分配的结果),但是在开发 C++ 时,他们将其更改为左值,以便与重载 operator= 并返回对 self 的引用(这是一个左值)的对象保持一致。
  • 干得好。我知道这与关于右值和左值的不同规则有关,但我正在研究 & 运算符而不是 = 运算符。 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多