这让我很困惑:
#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;通过一些但不是所有表达的财产。
答案 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,因此无法使用++。
答案 3 :(得分:-1)
假设
int a = 0, b = 1;
int *ptr_a = &a;
int *ptr_b = &b;
我们可以增加具有某个位置的变量的值。 如果你试图修改一个常量然后你得到错误L值需要意味着所需的位置和常量没有任何位置,因此错误。