为什么
(a?b:c)=5;
中的
表示
时需要左值 *(a?&b:&c)=5;
完全没问题?这两者有什么区别?
假设a = 1,对于第一种情况,它给出b = 5,第二种情况给出,*(&b)=5
。“
我无法理解的是:如果我们写b=5
或*(&b)=5
会有什么不同?
答案 0 :(得分:6)
如果我们写b = 5或*(& b)= 5?
,会有什么不同
第二个获取指向b
的指针,然后取消引用该指针,将5存储到获取的指针中。
但是,你的问题似乎忽略了真正的问题:为什么它在第二种情况下工作,而不是第一种情况。这与C中的表达式以及如何处理它们有关。
?:
运算符的结果是一个值;具体来说,它是 rvalue 。松散定义,rvalue是一个不能在赋值的左侧进行的值。它们之所以如此命名,是因为它们的价值落在作业的右侧。例如,表达式“5”是右值表达式。你无法做5 = 40;
这是胡说八道。
命名变量是左值。您可以在等式的左侧放置左值。表达式a
是一个左值表达式(假设a
是一个在范围内的变量名)。
但是,表达式(a + b)
是 rvalue表达式,而不是左值。有充分的理由;你不能再(a + b) = 30;
做(5 + 10) = 30;
。
?:
运算符的结果是一个右值表达式,就像上面的+
运算符一样。这解释了为什么(a?b:c) = 5;
不起作用;您正在尝试为rvalue表达式赋值。这是非法的。
现在,让我们看看第二种情况。我们知道?:
会导致rvalue表达式。现在,这解释了表达式的分类是什么,但表达式结果的类型呢?好吧,假设b
和c
都是int
s,(a?b:c)
的类型也是int
。
但是,当您执行(a?&b:&c)
时,此表达式的类型为 int*
,而不是int
。它是一个整数的指针。它是“指向int
的指针”的右值表达式。它将返回b
的地址或c
的地址。
如果您有int*
,并且使用*
运算符取消引用它,您会得到什么?您将获得int
类型的 左值表达式 。由于(a?&b:&c)
是int*
类型的右值表达式,如果取消引用它,您将得到类型为int
的左值表达式。该左值将引用b
或c
,具体取决于a
的内容。
简而言之,它的工作原理如下:
int *ptr = NULL;
if(a)
ptr = &b;
else
ptr = &c;
*ptr = 5;
你得到一个指针,它可以指向任何特定的内存位置,然后你在指向的位置存储一些东西。就这么简单。