C如何推断“可分配值”/ l值

时间:2014-03-21 09:20:18

标签: c dereference lvalue

这让我很困惑:

#include <stdio.h>

int main(int argc, char** argv) {
  int a = 0, b = 1;
  int *ptr = argc <= 1 ? &a : &b;
  (*ptr)++; //does work, of course

  (*(argc <= 1 ? &a : &b))++; //inlining, does also work

  int *ptr_a = &a;
  int *ptr_b = &b;

  (*(argc <= 1 ? ptr_a : ptr_b))++; //variables carry "assignability"

  (argc <= 1 ? *ptr_a : *ptr_b)++; //if-expression does not carry "assignability"?

  return 0;
}

我总是认为&#34;可转让性&#34;是一个类型属性。因此,我认为最后的陈述应该工作得很好,而不是被拒绝。那么,为什么取消引用必须是C编译器的最外层运算符才能确定lhs实际上是一个内存位置?

编辑:我怀疑它与OS /编译器有关,但与C标准有关,但这是我的编译器设置:

clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-redhat-linux-gnu
Thread model: posix

这是错误:

test.c:15:32: error: expression is not assignable
  (argc <= 1 ? *ptr_a : *ptr_b)++; //if-expression does not carry "assignability"?

edit2:我最感兴趣的是,为什么C似乎带有&#34;可转让性&#34;通过一些但不是所有表达的财产。

4 个答案:

答案 0 :(得分:2)

请注意,derefernce *运算符在应用于指针时会返回l值

的情况下
(*(argc <= 1 ? &a : &b))++;

返回&a&b(r值,但会返回指针)。之后, derefernce应用于两个指针中的任何一个,这将返回一个l值。增量运算符可以应用于它,因为它需要一个l值作为其操作数 你也可以理解为;如果argc = 1,那么表达式就像

*(&a);

&a返回a的地址,并且引用它将返回l值。

如果是

(argc <= 1 ? *ptr_a : *ptr_b)++;  
返回

*ptr_a*ptr_b(在这种情况下返回r值)。由于增量运算符++的操作数必须是l值,因此上述语句将产生错误。

答案 1 :(得分:2)

在C中,三元运算符始终返回r值 - Conditional operator differences between C and C++

在第二个示例中,您直接对其应用后增量,但该运算符需要l值,因此它不是有效代码。

在第一个示例中,您执行指针解除引用,将其转换为l值,因此代码有效。

答案 2 :(得分:1)

问题是C中的条件运算符促使第2和第3个操作数相互匹配。提升变量是右值而不是左值,因此?:总是返回右值

另一方面,*运算符返回一个左值。这就是为什么(*(argc <= 1 ? ptr_a : ptr_b))++有效,因为++应用于*的结果,这是一个左值。

但是在(argc <= 1 ? *ptr_a : *ptr_b)的情况下,结果是rvalue,因此无法使用++。

Please note that C and C++ are different in this case.

答案 3 :(得分:-1)

假设

  int a = 0, b = 1;
  int *ptr_a = &a;
  int *ptr_b = &b;

我们可以增加具有某个位置的变量的值。 如果你试图修改一个常量然后你得到错误L值需要意味着所需的位置和常量没有任何位置,因此错误。