C语言_运算符_语句
优先级表格
左结合的意思:先计算运算符左侧的内容;右结合就是先计算运算符右侧的内容。
举几个例子
1 | - 5 + 3 % 2 -> -4 |
-
后置
++
是等整个表达式计算完之后,再进行++
;前置++
是先++
再参与到表达式中。 -
自增自减符(
++
、--
)只能用于更改具名的变量,不能更改没有固定内存地址的操作数。 -
而加减乘除(
+
-
*
/
)不能修改操作数,只能把每个操作数串联起来,组成表达式,最后计算值。 -
能改变变量本身的运算符只有
++
、--
和赋值运算符(=
+=
&=
>>=
等等)
赋值运算符
1 | x = 3 * 4 -> x为12, 表达式也为12 |
关系运算符
1 | //a = 100, b = 99, c = 101, ch = 98 |
比较大小的关系运算符会返回boolean(真、假),其中0代表假,非零代表真。系统返回的真值默认为1。
逻辑运算符&&
||
&&
比||
优先级高。
1 | //a = 100, b = 99, c = 101, x = 4, y = 6 |
逗号(坑)
- 逗号用在3个地方。一个是定义和初始化,一个是逗号表达式,还有传参的分隔。
- 逗号运算符是优先级别最低的(一定要记住,比
=
还低)。 - 逗号运算符遵循左结合,即从左到右依次计算,最后逗号表达式的值为最右边的值。
1 | int main(void) |
定义和初始化
1 | int x = 5, y = 7; |
1 | int x = 5, y = 7, z = 0; |
函数传参中的逗号
这里会有坑出现。( 类似于量子测不准现象 doge
1 | printf("%i\n", x + y, 6 - y, 9 ); //打印出来为 x+y -> 12 |
这是因为,printf函数中有可变参,如果不加括号,则会把逗号视为参数的分隔符。
1 | printf(const char * const format, ...) |
后置++
和逗号的爱恨情仇
1 | int x = 5, y = 7, z = 0; |
在本次测试中,逗号表达式的值为9,即y在逗号表达式结束前就自增了,也就是说后置++
这个平时动作最慢的老家伙也穿越不了逗号。看来逗号可以被封为无敌懒神。
然而,这只是本次测试的情况,后置++
有时候比较讨厌,行为有时不一致,这和不同编译器不同的实现有关。
1 | int x = 5, y = 7, z = 0; |
括号是++
和逗号的他俩的定心丸(其实也称得上搅屎棍),如果括号去掉,则z最后就等于12,即在y自增前把x+7赋给z。
按位运算符
位运算符直接操作变量的机器码(二进制)。
应用
- 网络程序中有时要专门处理某些位
- 工业控制中控制标识位
- 异或用于加密
1 |
要求,在不干扰其他灯的情况下,让B灯亮,按位或:
1 | 1000 -> 1010 |
检查B灯的亮灭,按位与:
1 | 1000 -> 返回一个0值或非0值 |
灭掉B,先按位非后按位与:
1 | 1010 -> 0000 |
异或用于加密:
1 | text -> 1101 |
移位运算符
1 | int main(void) |
1 | int main(void) |
1 | int main(void) |
可得,对于有符号数,移位运算符保留了符号属性。如果不想保留符号特性,可以让操作数强制转为unsigned,如下:
1 | int main(void) |
总结
(笃定地讲)所有表达式最后肯定会产生一个临时值,如果没有值产生,就不是表达式,而是一个语句。
语句
-
顺序语句
-
分支语句
- if
-
循环
- while
- do-while
- for
分支语句
1 | int main(void) |
1 | int main(void) |
switch-case
1 | int main() |
上面这个程序的所达到的效果,在逻辑上,if-else和switch-case是一样的。
switch后面括号内的变量只支持整型或枚举类型,枚举类型也是整型的一种。
如果分支很多且判别表达式值为整型,则使用switch-case更合适。
如果抛去这两个限制(分支的多少和判别表达式值的类型),则性能上switch-case更有优势:
- 编译器直接把case中的编号当做偏移量,对应到相应的内存地址上了。
- 于是直接略过了判断前面的过程,直接去找相应的分支。
循环
while
1 | int main(void) |
1 | int main(void) |
continue
1 | int main(void) |
求1到100加和:自然终止
1 | int main(void) |
求1到100加和:条件break终止
1 | int main(void) |
do-while
不管while括号内条件是否符合,至少执行一次循环体。
1 | int main() |
for
for后的括号内是三条语句。第一条只运行一次,第二条是每次进入循环时都要判断,第三条是每次循环体运行完后执行。
1 | int main(void) |
九九乘法表
1 | int main(void) |
printf
中的%-2i
代表有符号整数,附加的效果是占两位,左对齐(负号的作用)。for
表达式中的第三个表达式是最后做的处理,往往不需要返回值。在本例中,第一层for循环代表行的处理,第二层for循环代表列的处理,每当第二层for循环完毕后,需要换行,即每当第一层for循环体内容结束后,需要做两个事情:1、i加1;2、换行,可以合并为逗号表达式放在for表达式第三个空中。因为for括号中的第三个语句没有人来接受它的返回值,所以可以直接写printf这种无返回值的函数。
总结
- while循环往往适用于不清楚运行次数的,不能精准控制步长的情况。
- for循环适用于知道运行次数的情况:需要明白i的范围、步长。