表达式
表达式是由运算符、运算量和标点符号组成的有效序列,其目的是用来说明一个计算过程,表达式可以独立成句,一般形式为:
表达式;
运算符
运算符可以按照功能分为:算术运算符、赋值运算符、关系运算符、逻辑运算符、位运算符和其他运算符。
算术运算符
算术运算符有:+ - * / % ++ --
除法(/)
除法规则:整数相除,向下取整。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char const * argv[])
{
int a=3/2;
float b=3/2;
float c=3.0/2;
printf("a=%d b=%f c=%f\n",a,b,c);
reutrn 0;
}
以上代码的输出结果为:
整除(%)
整除规则:只能用于整数运算,取余数。
将12345的个十百千万位分别输出到终端
#include <stdio.h> #include <stdlib.h> int main(int args,char const * argv[]) { int number=12345; int w,q,b,s,g; w=number/10000; q=number/1000%10; b=number/100%10; s=number/10%10; g=number%10; printf("%d %d %d %d %d\n",w,q,b,s,g); reutrn 0; }
以上代码输出结果为:1 2 3 4 5
自增(++)和自减(--)
int a=0; a++; ++a;
以上两条都相当于a=a+1;
int a=1,b=1;
a++;
++b;
printf("%d %d\n",a,b); //2 2
int a=0; a--; --a;
以上两条都相当于a=a-1;
自加和自减规则:
++或--在前时,先进行++或--操作再进行赋值打印;
++或--在后时,先进行赋值打印再进行++或--操作;
#include <stdio.h>
#include <stdlib.h>
int main(int args,char const *argv[])
{
int a=1,b=1;
printf("%d %d\n",++a,b++); //2 1
printf("%d\n",b); //2
/*相当于
printf("%d\n",b);
b++;
*/
return 0;
}
赋值运算符
赋值运算符有:= += -= *= /=
++或--在前时,先进行++或--操作再进行赋值打印;
++或--在后时,先进行赋值打印再进行++或--操作;
例如:
z=++x + y++;
相当于:
x=x+1;
z=x+y;
y=y+1;
#include <stdio.h> #include <stdlib.h> int main(int args,char const *argv[]) { int x=1,y=2,z=0; z=++x+y++; printf("x=%d y=%d z=%d\n"); //2 3 4 return 0; }
以上输出结果为:x=2 y=3 z=4
加等于(+=)
a+=2相当于a=a+2
同理,a-=2相当于a=a-2,a*=相当于a=a*2,a/=2相当于a=a/2
#include <stdio.h> #include <stdlib.h> int main(int argc,cahr const * argv[]) { int a=10; int b=a++; //b=10,a=11 int c=a+b; //c=21,b=10,a=11 int d=(b++)+c; //b=11,c=21,d=10+21=31 printf("a=%d b=%d c=%d d=%d\n",a,b,c,d); return 0; }
以上输出结果为:a=11 b=11 c=21 d=31
#include <stdio.h> #include <stdlib.h> int main(int args,char const * argv[]) { int a=10; int b=++a; //b=11,a=11 int c=a+(b++); //a=11,c=11+11=22,b=12 int d=b+c; //b=12,c=22,d=12+22=34 printf("a=%d b=%d c=%d d=%d\n",a,b,c,d); return 0; }
以上输出结果为:a=11 b=12 c=22 d=34
关系运算符
关系运算符有:> >= < <= == !=
关系运算符是用来判断两者的关系,如果满足判断条件返回真,如果不满足返回假
运算符 | 名称 | 示例 | 功能 | 缩写 |
< | 小于 | a<b | a小于b时返回真,否则返回假 | LT |
<= | 小于等于 | a<=b | a小于等于b时返回真,否则返回假 | LE |
> | 大于 | a>b | a大于b时返回真,否则返回假 | GT |
>= | 大于等于 | a>=b | a大于等于b时返回真,否则返回假 | GE |
== | 等于 | a==b | a和b相等时返回真,否则返回假 | EQ |
!= | 不等于 | a!=b | 不等于b时返回真,否则返回假 | NE |
逻辑运算符
逻辑与(&&)
逻辑与的规则:全真则真,一假则假
逻辑或( || )
逻辑或的规则:一真则真,全假则假
逻辑非( !)
逻辑非的规则:非真为假,非假为真
#include <stdio.h> #include <stdlib.h> int main(int args,char const *argv[]) { int a=2,b=3; printf("%d\n",0&&1); printf("%d\n",0||0); printf("%d\n",(a<=b)&&(a==2)); printf("%d\n",!(a>b)); return 0; }
以上输出结果为:
0
0
1
1
短路法则(截断法则)
逻辑或( || )运算中:
如果前面的表达式为真,则后面的表达式不用执行,结果为真。
逻辑与(&&)运算中:
如果前面的表达式为假,则后面的表达式不用执行,结果为假。
#include <stdio.h> #include <stdlib.h> int main(int args,char const *argv[]) { int a=5,b=6,c=7,d=8,m=2,n=2; int r=(m=a<b)||(n=c<d); printf("%d %d %d\n",m,n,r); //用到了短路法则,逻辑或(||)前面公式判断为真后面不执行,结果为真 r=(m=a>b)&&(n=c<d); printf("%d %d %d\n",m,n,r); //用到了短路法则,逻辑与(&&)前面公式判断为假后面不执行,结果为假 return 0; }
以上输出结果为:
1 2 1
0 2 0
题目:
给出一个年份,判断是平年还是闰年,如果是闰年打印1,如果是平年打印。
提示:
闰年和平年的区别就是闰年的二月份比平年的二月份多一天。判断闰年还是平年的依据:
普通年份除以4,有余数的是平年,没有余数的是闰年;
整百年份除以400,有余数的是平年,没有余数就是闰年。
思路:
可以设置一个标志位flag来接收是平年还是闰年的结果,然后用逻辑运算来判断是平年还是闰年,最后打印出来flag
#include <stdio.h> #include <stdlib.h> int main() { int flag=0,year; scanf("%d",&year); flag=((year%4==0&&year%100!=0) || (year%400==0)); printf("%d\n",flag); return 0; }
位运算符
含义 | C语言表达式 |
按位与 | a&b |
按位或 | a | b |
按位异或 | a ^ b |
按位取反 | ~ a |
左移 | a<<b(a左移b位) |
右移 | a>>b(a右移b位) |
无符号右移 | / |
需要注意的是,负数都是用补码进行运算。
位与(&)
位与规则:全1则1,有0则0
例如:
5&6
0000 0101
& 0000 0110
————————
0000 0100
位或(|)
位或规则:有1则1,全0则0
例如:
5| 6
0000 0101
| 0000 0110
————————
0000 0111
位异或(^)
位异或规则:不同为1,相同为0
例如:
15| 16
0000 1111
| 0001 0000
————————
0001 1111
按位取反(~)
按位取反规则:按位取反,0变1,1变0
原码 | 反码 | 补码 | |
正数 | 正数本身 | 正数本身 | 正数本身 |
负数 | 负数本身 | 除符号位外,其余按位取反 | 反码+1 |
例如:
~15:
0000 1111
~ ———————
1111 0000
~-1:
1000 0001
~ ———————
1111 1110
原码 反码 补码 1 0000 0001 0000 0001 0000 0001 -15 1000 1111 1111 0000 1111 0001
左移(<<)
左移规则:左移几位,右边补几个0
例如:
8<<2: ==> 0000 1000<<2
==> 0010 0000=32
-5<<3:
原码:1000 0101
反码:1111 1010
补码:1111 1011
<<3: ==> 1101 1000 //负数用补码计算
左移后的原码:1010 1000=-40
右移(>>)
右移规则:右移几位,左边补几个符号位(即正数补0,负数补1)
例如:
8 >> 2:
0b 0000 1000 >> 2
0b 0000 0010=2
-10 >> 3:
原码:1000 1010
反码:1111 0101
补码:1111 0110
>>3: ==> 1111 1110//负数用补码计算
左移后的原码:1000 0000=-2
置一公式和置零公式
置一公式:a | (1<<n)
置零公式:a&(~(1 << n))
int a=0b0111; printf("%d\n",a|(1<<3)); //0b111=15 printf("%d\n",a&(~(1<<2))); //0b0011=3
以上输出结果为:
15
3
其他运算符
三目运算符(条件运算符)
三目运算的表达式:
表达式1?表达式2:表达式3
执行逻辑:先求解表达式1,如果其值为真(非0)则执行表达式2作为整个表达式的结果,否则(也就是表达式1的值为假)执行表达式3作为整个表达式的结果。
例如:
#include <stdio.h> #include <stdlib.h> int main(int args,char const *argv[]) { int a=5,b=6,max=0; max=a>b?a:b; printf("max=%d\n",max); return 0; }
以上输出结果为:max=6
int num1=10,num2=20; int res=num1>num2?num1++:num2++; printf("num1=%d num2=%d rea=%d\n",num1,num2,res);
以上输出结果为:10 21 20
运算符优先级
口诀:
单算移关与,异或逻条赋
从右向左单条赋
设int b=2;表达式(b>>2)/(b>>1)的值是(0)
解析:b>>2=0 b>>1=1 ==> 0/1=0
整型变量x和y的值相等,且为非零值,则下列表达式中结果为0的是(D)
A. x || y B.x | y C.x & y D.x ^ y
以下程序的输出结果是(100)
int main() { char x=040; printf("%o\n",x<<1); return 0; }
解析:将x转换为二进制在左移一位后转换为八进制
040=0b 0100 0000
左移一位后:0b 1000 0000
转换为八进制为:0100
以下程序的运行结果为(11 22)
int main() { unsigned char a,b,c; a=0x3; b=a | 0x8; c=b<<1; printf("%d %d\n",b,c); retrn 0; }
解析:a=0b 0000 0011
b=0b 0011 | 0b 1000 = 0b1011 = 11
c=0b 1011 << 1 = 0b 0001 0110=22
设char型数据变量x中的值为1010 0111,则表达式(2+x)^(~3)的值为(0101 0101)
解析:2+x=0b 0000 0010 + 0b 1010 0111=0b 1010 1001
~3=0b 1111 11100
0b 1010 1001 ^ 0b 1111 11100 = 0b 0101 0101