MyCDay4
表达式
- 表达式:计算某个值的“公式”;表达式是有值的。最简单的表达式:变量、常量。
- 语句:语句没有值。往往会产生一些“副作用”。会改变程序的状态
- 运算符:连接表达式,创建更复杂的表达式。
- 算术运算符
- 逻辑运算符
- 三目运算符
- 关系运算符
- 赋值运算符
- 位运算符
两个重要属性:
- 优先级
- 结合性
运算符
算术运算符
+ - * /
注意事项:
1.+ - * /
可以用于浮点数,%
不能用于浮点数。
2.两个整数相除。结果为整数。(向零取整)4/3— 1 5/3— 1 -4/3— -1 -5/3— -1
3.
i%j
结果可能为负,符号与i
相同4%3=1 4%-3=1 -4%3=-1 -4%-3=-1 //判断一个整数是否为奇数. 错误 bool isOdd(int n){ return n%2==1; //-3%2=-1 } bool isOdd(){ //正确 return n%2!=0 } bool isOdd(){ return n& 0x1 }
赋值运算
- 简单赋值
v=e
把表达式e
的值赋值给变量v
(副作用),整个表达式的值是赋值后v
的值- 注意事项:
1. 赋值过程中可能发生类型转换int i=3.14;
2. 结合性:从右向左结合i=(j=(k=3));
- 注意事项:
- 复合赋值运算符
a+=b <--->a=a+b
a-=b <--->a=a-b
a*=b <--->a=a*b
a/=b <--->a=a/b
自增和自减运算符
- 自增:i=i+1,i+=1,
- 自减:i=i-1,i-=1,
- C语言专门提供两个用于自增,自减的运算符
++
and--
i++
:表达式的值为i,副作用是i自增i—
:表达式的值为i,副作用是i自减- 注意事项:不要这样写!
i=i++;
j=(i++)+(++i)
a[i]=b[i++]
都会产生未定义的行为
- -i
:表达式的值为i-1,副作用是i自减
++i
:表达式的值为i+1,副作用是i自加
关系运算符
< , > , <= , >=
其结果要么为0,要么为1
注意事项:
10<j<20,先计算10<其结果要么为0,要么为1,(1、0)<10,最终结果为1.
j>10&&j<20 <--->j(10,20)
判等运算符
==,!=
其结果 0/1
逻辑运算符
! &&. ||
注意事项:&&
和||
会发生短路现象。
e1&&e2
先计算e1的值,若e1为0,则不会再计算e2的值。
e1||e2
先计算e1的值,若e1为1,这不会计算e2的值。int i=10; (i++>20)&&(++i<30); //后面++i不计算 //i=11; (i++>10)||(++i<30) //两边都计算 //ii=12
好处:方便编写代码
if(i!=0&&j/i>2){// }
位运算符 (****)
<<,>>
左移 右移
~
按位取反
``
- 移位运算符
i<<j
i左移j位,右边补0
0000 0000 0000 1101 ———<<2———0000 0000 0011 0100
13—————————————————————52
若没有发生溢出,左移j位,相当于乘以2j
注意:位移运算时,右操作数会先取余,然后再移位
i>>j
:i右移j位,若i为无符号整数或非负数,则左边补0;若i为负数,它的行为是由实现决定的,有的补0,有的补1!
注意:为了代码的可移植性,不要对有符号整数进行移位运算。
2.按位运算符
~i
0000 0000 0000 0011
—————>1111 1111 1111 1100
(-4)
i&j
0000 0000 0000 0011
0000 0000 0000 0100
0000 0000 0000 0000
(0)
i|j
0000 0000 0000 0011
0000 0000 0000 0100
0000 0000 0000 0111
(7)
i^j
异或 相同为0,不同为10^0=0,1^1=0,0^1=1,1^0=1
0000 0000 0000 0011
0000 0000 0000 0100
0000 0000 0000 0111
(7)
性质
a^0=a
a^a=0
a^b=b^a
(a^b)^c=a^(b^c)
例题:
1.如何判断一个数是否为奇数?
bool isOdd(int n){
Return n&0x1; //非0为正,奇数最后一位为1,1&1=1;偶数最后一位为0,0&1=0,0为false
}
2.如何判断一个整数是否为2的幂?1,2,4,8,16……
3. 给定一个不为0的整数,找出last set bit
输入:0011 0100
输出:4
解答:
0011 0100
1100 1100 &运算
0000 0100 (4)
4. 给定一个数组,里面的整数都是成对出现的,只有一个数例外,请找出这个数。
输入:[1,2,3,4,4,5,6,3,1],9
输出:5
- 给定一个数组,里面的整数都是成对出现的,只有两个例外,找出这两个数。
语句
- 语句
- 表达式语句(在表达式后面添加
;
) - 选择语句(
if switch
) - 循环语句(
while do…while for
) - 跳转语句(
break continue goto
) - 空语句(
;
); - 复合语句(
{多条语句}
,将多条语句{}括起来,组成一条语句)
- 表达式语句(在表达式后面添加
选择语句
-
格式1:
if (expression) { statements. }
-
格式2:
if (expression) { statements. }else{statements}
级联式if语句本质上是if语句的嵌套!
switch 语句
最常见的格式
switch (expression) {
case exp1:statement;break;
case exp2:statement;break;
default:statement;break;
}
注意事项:
- expression必须是整数类型(也可以是char类型),不能是浮点数和字符串(指针)。switch是通过
==
进行比较的。- case后面的exp必须在编译期间求值。
- 不能够有重复的标签
- 多个标签可以公用一组语句
- break语句可以省略,但省略之后可能出现case穿透现象!
比较:级联式if语句和switch语句
1. 所有的switch语句都可以改写成级联式 if语句,级联式if语句更通用
2. switch语句的执行效率一般比if语句高。
3. switch语句可读性比if语句高。
三目运算符
- 格式:
expr1?expr2:expr3
- 计算顺序:先计算expr1的值
- 如果expr1为真,则计算expr2的值,并把expr2的值当做整个表达式的值
- 如果expr1为假,则计算expr3的值,并把expr3的值当做整个表达式的值
循环语句
1.while 语句
格式:while(express条件语句){statements循环体}
2.do…while语句
格式:
do {
statements//循环体
}while (expression)//条件表达式
while and do…while 的区别:
while的循环体可能一次都不执行;do…while的循环体至少执行一次。(当条件表达式的初始值为0时)
3.for语句
- 格式:
for (init-statement; condition; inc-expression) {
statements
}
expr1:初始化表达式,只执行一次
expr2:条件表达式
expr3:执行完循环体之后,要计算的表达式
注意事项
expr1,expr2,expr3都可以省略,如果expr2省略,其默认值为真
跳转语句
- 跳转语句
- break
- continue
- goto
1.break
- 作用:跳出switch或循环语句
注意事项
当switch语句、循环语句嵌套时,break只能跳出包含break语句的最内层嵌套。
2.continue
continue和break的区别:
1.break可以用于循环语句和switch语句;continue只能用于循环语句。
2.break是跳出整个循环,continue是跳转到循环体的末尾
3. goto 语句
break,continue的作用是受限制的。
goto可以在函数内进行任意的跳转。
- Q1:为什么还需要break和continue?
1. 可读性
2. 受限更安全,滥用goto很容易出现BUG
《goto statement considered harmful》
- 格式:goto 标签(标识符);
- 使用场景:
-
跳出外层嵌套
-
错误处理
-