一、逗号表达式
(exp1, exp2, ... , expN)
:逗号表达式的值等于最后一个表达式的值
int main() {
int x = 10;
int y = 10;
int z = (x++, ++y, x + y); // 22
int arr[3][4] = { (1,2,3,4), (5,6,7,8),(9,10,11,12) }; // {4,8,0}
cout << arr[0][1] << " " << arr[1][2] << " " << arr[2][3] << endl; // 8, 0, 0
return 0;
}
二、后置++
a++可翻译为如下的逗号表达式:
(int tmp = a, a = a + 1, tmp) // 说明最后a的值加1,表达式返回的值为tmp
而这个tmp是一个临时量,相当于一个立即数,直接放在cpu的寄存器上,不占用任何内存,不能作为左值
比如这段代码编译不通过
int a = 10;
a++ = 100;
由于逗号表达式返回的是一个立即数,不能作为左值,所以编译不通过
三、前置++
++a可翻译为如下的逗号表达式:
(a = a + 1, a)
++a
返回的就是a本身,可以作为左值(有名字,有内存,值是可以被修改的)
int a = 10;
++a = 100; // a == 100
四、几个表达式
首先我们要知道编译器分析词法语法的原理,使用贪心思想,从左到右找到最长的且合法的运算符
1. a+++++b
像a+++++b
这个表达式,编译器是这样分析的:
首先+
合法,然后++
也合法,但是+++
不合法,于是断开。
我们现在有了a++
,编译器看到第三个+
断开了,于是看++
也合法,同理+++
不合法,于是断开。
我们现在有了a++
和++
,编译器接着往右看+
合法,然后看到+b
不是合法运算符,断开。
于是我们得到a++
、++
、+
、b
a++ ++ +b // 不是我们所理解的a++ + ++b
由于a++返回的是立即数,不是左值(有内存),所以不能进行++
我们还可以自己加上空格,帮助编译器按照我们希望的方式断句
2. ++a+++b
++a
是合法的,++
也合法,+++
不合法,于是表达式翻译如下:
++a++ +b;
++
是单目运算符,并且是右结合的,所以翻译如下:
++(a++) +b;
同理,a++返回的是立即数,不是左值(有内存),所以不能进行前置++
3. (++a)+++b
int a = 12;
int b = 10;
cout<< (++a)+++b; // 23
首先计算++a,这时a的值为13,然后执行a++,这个表达式返回一个立即数,还是13,而a的值已经变成了14,立即数13加上b,结果就是23
4. (++i) + (++i)
int i = 1;
int res = (++i) + (++i); // 6
// int res = (i = i + 1, i) + (i = i + 1, i);