1.运算符?是用来进行某种运算的符号几目运算符?这个运算符需要几个操作数就称为几目单目运算符双目运算符三目运算符结合性:从左至右从右至左当两个运算符的优先级是一样的,看结合性优先级
1.运算符?是用来进行某种运算的符号
几目运算符? 这个运算符需要几个操作数就称为几目
单目运算符
双目运算符
三目运算符
结合性 :从左至右 从右至左
当两个运算符的优先级是一样的,看结合性
优先级 :单目运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 条件运算符 > 赋值运算符 > 逗号运算符
(1)算术运算符
++ -- :单目运算符
* / % + - :双目运算符 ,结合性从左至右,先乘除后加减
eg:
5/4 =》 1 (整数进行算术运算其结果为整数)
5.0/4 => 1.25
double(3/2) =》1.0
(double)3/2 =》1.5
% :求余 ,要求两个操作数都必须为整数
5%4 =>1
4%5 =>4
用C语言的表达描述数学表达式 a/b => a*1.0/b
a+b 与 b+a 在C语言中含义是不一样的
i = 5,j = 6;
(i++) +(i+j) =>17
(i+j)+(i++) =>16
======================
表达式的值 做完表达式后i的值
i++ i i = i+1
++i i+1 i = i+1
i-- i i = i-1
--i i-1 i = i-1
eg:
i = 5;
a = i++;//把表达式(i++)的值赋值给a,i++这个表达式的值为5
a = (++i);
NOTE:
++ -- 隐含了 “赋值”
i = i+1;
i = i-1;
so :
(i+j)++ =>error
(1+2)++ =>error
i++ ; =>i必须要是一个变量
(2)关系运算符:用来判断两个东西的关系的运算符
<<= > >=
== !=
双目运算符, 从左至右
关系表达式 :用关系运算符连接起来的式子
关系表达式的值 : “关系成立 (1)” “关系不成立(0)”
eg:
5 > 4 =>1
3 <= 4 =>1
5 > 4 > 3 这是一个合法的表达式
5 > 4 > 3 =》(5>4)>3
=>1>3
=>0
数学上的5 > 4 > 3 与C语言中的含义是不一样的
如何描述我们数学上的5 > 4 > 3 ?
5 >4 并且 4 > 3
(3)逻辑运算符
! 逻辑非 单目运算符 取反
&& 逻辑与 双目运算符 从左至右 “并且”
|| 逻辑或 双目运算符 从左至右 “或者”
逻辑表达式 :用逻辑运算符连接起来的式子
逻辑表达式的值 :逻辑真(非0,1) 逻辑假(0)
&& :左右两边结果都为真 =》真
|| :左右两边只要有一者为真 =》真
eg:
a = 4,b = 5
a && b =>1
a || b =>1
!a|| b =>1
5 > 3 && 8 <4-!0
=>1 && 0 =>0
练习:
int a = 1,b = 2,c = 3,d = 4,m = 1,n = 1;
(m = a > b) && (n = c > d);
printf("%d %d %d %d %d %d \n",a,b,c,d,m,n);
=>1 2 3 4 0 1
// m = 0 n = 1
C语言运算符的“惰性运算”
(1) a && b && c
只有a为真,才需要判断b的值
只有a和b都为真,才需要判断c的值
(2)a || b || c
只要a为真,就不需要判断b和c的值
只有a为假,才需要判断b的值
只有a和b都为假,才需要判断c的值
(4)位运算符
位运算符是按照bit为来进行计算运算
& 按位与
| 按位或
^ 按位异或
~ 按位取反
<< 按位左移
>> 按位右移
除了~是单目运算符,其余都是双目运算符,结合性都是从左至右
位运算的操作数只能是整数(int/short/long/char)
所有的位运算都需要把操作数变成bit位序列,然后在进行操作
~ (按位取反) 单目运算符
0 ->1
1 ->0
int a = ~3;
printf("%d\n",a);//-4
printf("%u\n",a);//2^32-4
~3:
00000000 00000000 00000000 00000011
11111111 11111111 11111111 11111100
%d:
11111111 11111111 11111111 11111011 (-1)
00000000 00000000 00000000 00000100
%d =>-4
%u:
11111111 11111111 11111111 11111100
%u =>2^32-1-3
===========
int a = ~(-3);
printf("%d\n",a);//2
printf("%u\n",a);//2
-3 :
00000000 00000000 00000000 00000011 (3)
11111111 11111111 11111111 11111100 (取反)
11111111 11111111 11111111 11111101 (+1)
~(-3) 00000000 00000000 00000000 00000010
%d :
00000000 00000000 00000000 00000010
%u :
00000000 00000000 00000000 00000010
-3+4:
//==================================
& (按位与) :双目运算符 “与”
a b a&b
1 1 1
1 0 0
0 1 0
0 0 0
& :如果两个bit位操作数都为1 ,结果才为1
否则为0
eg :
3 & 5 == ?
00000011
00000101
& 00000001
假设有一个整型变量a.要把a的第5bit变为0,其他bit位不变,该如何操作?
a :xxxx....Xxxxxx
& :1111....011111 ~(1<<5) 00000000 00000000 00000000 00100000
a = a & ~(1<<5)
与1&为原值,与0|为原值
结论:
一个bit位与0进行“按位与”,其结果为0
x & 0 == 0
一个bit位与1进行“按位与”,其结果保留原值
x & 1 == x
(-3)&(-5) =>
-3 :11111101
-5 :11111011
& :11111001
//==========================
| (按位或) :双目运算符, 结合性从左至右
a b a|b
1 1 1
1 0 1
0 1 1
0 0 0
按位或,只有有一个bit操作数为1,其结果为1
假设有一个整型变量a.要把a的第5bit变为置1,其他bit位不变,该如何操作?
a :xxxx....Xxxxxx
| :0000....100000 (1 <<5)
a = a | (1<<5)
(-3)&(-5) =>-1
结论:
一个bit位与0进行“按位或”,其结果保留原值
x | 0 == x
一个bit位与1进行“按位或”,其结果为1
x | 1 == 1
//=======================
^ (按位异或) 双目运算符 “异或” 不同为1 相同为0
a b a^b
1 1 0
1 0 1
0 1 1
0 0 0
练习:
(-3)^(-5) =>6
假设有一个整型变量a.要把a的第5bit变为置1,其他bit位取反,该如何操作?
a = (a|(1<<5))^(~(1<<5))
假设有一个整型变量a.要把a的第5bit变为保留,其他bit位取反,该如何操作?
a :xxxx....Xxxxxx
^ :1111....011111
a = a^(~(1<<5))
结论:
一个bit位与0进行“按位异或”,其结果保留原值
x ^ 0 == x
一个bit位与1进行“按位异或”,其结果取反
x ^ 1 == ~x
//========================================
<<(按位左移) 双目运算符 将bit位整体往左边移
a <把a按bit位整体左移n位
高位左移后,丢弃,低位补0
如果左移后丢弃的高位全部为0 ,那么左移n位,就表示原值乘以2的n次方
1 <<5
>> (按位右移) : 双目运算符 将bit位整体往右边移
x >> n 把x按bit位整体右移n位
低位右移后,舍弃 ,高位?
有符号数 :高位全部补符号位
无符号数 :高位全部补0
int a = -1; //1111111 11111111 11111111 11111111
a = a >> 31;
printf("%d\n",a);//-1
======
unsigned int a = -1;//
a = a >> 31;//00000000 00000000 00000000 00000001
printf("%d\n",a);//1
(5) 条件运算符
?= 三目运算符
expression1 ? expression2 : expression3
上面是一个条件表达式:
如果expression1的值为真,则整个条件表达式的值为expression2这个表达式的值
如果expression1的值为假,则整个条件表达式的值为expression3这个表达式的值
eg:
a = 5>4 ? 4 :3;
(6)赋值运算符 双目运算符 ,从右至左
=
a = 5+3;// 赋值运算符的左边必须是一个可写的地址(左值)
赋值表达式 :有赋值运算符连接起来的式子
赋值表达式的值就是最后赋值后左边变量的那个值
a = 6;
b = a = 5;//合法
复合的赋值运算符:赋值运算符和算术运算符,位运算符组成的复合的运算符
+= -= %= *= /=
<<= >>= |= &= ^=
a += 1 =》a = a+1
a += 5+6 => a = a +(5+6)
(7) 逗号运算符: 双目运算符 优先级最低 从左至右
表达式1,表达式2
逗号表达式的求值顺序 :
先求表达式1的值,然后再求表达式2的值
整个表达式的值是表达式2的值
int a = 5,b = 6;
a = (a=6,a+b); =>12
逗号表达式值扩展:
表达式1,表达式2,....表达式n
求值顺序 :
先求表达式1的值,然后再求表达式2的值,再求表达式3的值
....一直求导表达式n的值
整个表达式的值是表达式n的值
(8)指针运算符
*(指向) &(取地址符)
(9)求字节运算符 (sizeof)
sizeof() :运算时只看括号内是什么数据类型,单位是字节
sizeof(1) =>4
sizeof(1.0) =>8
int a;
sizeof(a+1) =>4
sizeof(a+1.0) =>8
printf("%d\n",sizeof(1.0));
(10) 分量运算符
用来求结构体变量的成员变量
.
->
(11)下标运算符
[] :用来求取数组元素
int a[10];//定义了一个数组,数组名a,里面有10个int元素
a[0]
(12)强制类型转换运算符
(类型)值
float f = 3.6;
(int)f +3.5 => 6.5
(int)(f+3.5) =>7
(13)其他
函数调用运算符
2.表达式表达某个意思的式子
在C语言中一般是用运算符连接操作数的式子,叫表达式
是表达式就有一个值 =》表达式的值 =》表达式值类型
作业:答案
第一题(x>>p)& ((1<
第二题 上题取出来| (y & ( ~0 <第三题 x ^ ( ( ( 1 <第四题 (x & ( ( 1 <>n
第二次尝试:
1.取x中第p位开始的n个bit位
//先将x左移p是可以的,4个1,依次左移1,相与
//大哥的思路 (x>>p)&(~(-1<
2.将x中第p位开始的n个bit位设置为y中最右边的n位的值
x的其余位不变
//用000111000这种的取到n之后的数值,再进行右移p位
//自己感觉,用~(-1)进行取到所有的X,之后直接右移P位,但不知道会不会破坏原来的//数值 (x&(~(-1)))>>p ((x>>p)&(~(-1<)|(y<)
3.将x中第p位开始的n个bit位取反,其余位不变
//异或001100这种字符串
//反正都是用-1,想到先右移p,再左移p,再全部相异或 x^(((-1)>>p)<4.将x循环右移n位
//还是用-1进行处理,((x | (-1) <> n)
5.
分析以下程序的输出结果
char c = -56 >> 30;
printf("%d\n",c);
printf("%u\n",c);
========
char c = -56u >> 30;
printf("%d\n",c);
printf("%u\n",c);
第一次尝试:
// 1.取x中第p位开始的n个bit位
//1<<(p + 1)..1<<(p + n) 每个与P进行按位与 ,最后叠加也进行与就好 再合并就好应该来说。。
// 2.将x中第p位开始的n个bit位设置为y中最右边的n位的值
// x的其余位不变
//逆运算
// 3.将x中第p位开始的n个bit位取反,其余位不变
//将n左移之后异或
// 4.将x循环右移n位
//取第一位,全体左移,替换最后一位
// 5.
// 分析以下程序的输出结果
// char c = -56 >> 30;
//-56补码 24个1 1100 0111 右移30位后 32个1 再取8位
// printf("%d\n",c);
//补码8个1,所以得到答案 -1与255
// printf("%u\n",c);2^32 - 1
// ========
// char c = -56u >> 30;
//-56补码 24个0 1100 0111 右移30位后 32个1 再取8位
// printf("%d\n",c);右移后全为0 3 3 结果
// printf("%u\n",c);
运算符优先级
优先级 |
运算符 |
名称或含义 |
使用形式 |
结合方向 |
说明 |
1 |
[] |
数组下标 |
数组名[整型表达式] |
左到右 |
|
() |
圆括号 |
(表达式)/函数名(形参表) |
|
. |
成员选择(对象) |
对象.成员名 |
|
-> |
成员选择(指针) |
对象指针->成员名 |
|
2 |
- |
负号运算符 |
-算术类型表达式 |
右到左 |
单目运算符 |
(type) |
强制类型转换 |
(纯量数据类型)纯量表达式 |
|
++ |
自增运算符 |
++纯量类型可修改左值表达式 |
单目运算符 |
-- |
自减运算符 |
--纯量类型可修改左值表达式 |
单目运算符 |
* |
取值运算符 |
*指针类型表达式 |
单目运算符 |
& |
取地址运算符 |
&表达式 |
单目运算符 |
! |
逻辑非运算符 |
!纯量类型表达式 |
单目运算符 |
~ |
按位取反运算符 |
~整型表达式 |
单目运算符 |
sizeof |
长度运算符 |
sizeof 表达式 sizeof(类型) |
|
3 |
/ |
除 |
表达式/表达式 |
左到右 |
双目运算符 |
* |
乘 |
表达式*表达式 |
双目运算符 |
% |
余数(取模) |
整型表达式%整型表达式 |
双目运算符 |
4 |
+ |
加 |
表达式+表达式 |
左到右 |
双目运算符 |
- |
减 |
表达式-表达式 |
双目运算符 |
5 |
<< |
左移 |
整型表达式<<整型表达式 |
左到右 |
双目运算符 |
>> |
右移 |
整型表达式>>整型表达式 |
双目运算符 |
6 |
> |
大于 |
表达式>表达式 |
左到右 |
双目运算符 |
>= |
大于等于 |
表达式>=表达式 |
双目运算符 |
< |
小于 |
表达式<表达式 |
双目运算符 |
<= |
小于等于 |
表达式<=表达式 |
双目运算符 |
7 |
== |
等于 |
表达式==表达式 |
左到右 |
双目运算符 |
!= |
不等于 |
表达式!= 表达式 |
双目运算符 |
8 |
& |
按位与 |
整型表达式&整型表达式 |
左到右 |
双目运算符 |
9 |
^ |
按位异或 |
整型表达式^整型表达式 |
左到右 |
双目运算符 |
10 |
| |
按位或 |
整型表达式|整型表达式 |
左到右 |
双目运算符 |
11 |
&& |
逻辑与 |
表达式&&表达式 |
左到右 |
双目运算符 |
12 |
|| |
逻辑或 |
表达式||表达式 |
左到右 |
双目运算符 |
13 |
?: |
条件运算符 |
表达式1? 表达式2: 表达式3 |
右到左 |
三目运算符 |
14 |
= |
赋值运算符 |
可修改左值表达式=表达式 |
右到左 |
|
/= |
除后赋值 |
可修改左值表达式/=表达式 |
|
*= |
乘后赋值 |
可修改左值表达式*=表达式 |
|
%= |
取模后赋值 |
可修改左值表达式%=表达式 |
|
+= |
加后赋值 |
可修改左值表达式+=表达式 |
|
-= |
减后赋值 |
可修改左值表达式-=表达式 |
|
<<= |
左移后赋值 |
可修改左值表达式<<=表达式 |
|
>>= |
右移后赋值 |
可修改左值表达式>>=表达式 |
|
&= |
按位与后赋值 |
可修改左值表达式&=表达式 |
|
^= |
按位异或后赋值 |
可修改左值表达式^=表达式 |
|
|= |
按位或后赋值 |
可修改左值表达式|=表达式 |
|
15 |
, |
逗号运算符 |
表达式,表达式,… |
左到右 |
从左向右顺序结合 |
|
|
|
|
|
|
作业答案1.取x中第p位开始的n个bit位
(x >> p)&((1<
2.将x中第p位开始的n个bit位设置为y中最右边的n位的值
x的其余位不变
((x>>p)&((1<
3.将x中第p位开始的n个bit位取反,其余位不变
x^(((1<
4.将x循环右移n位
(x&((1<>n
5.
分析以下程序的输出结果
char c = -56 >> 30;
printf("%d\n",c);//-1
printf("%u\n",c);//2^32-1
-56的补码;
11001000
11111111
========
char c = -56u >> 30;
printf("%d\n",c);//3
printf("%u\n",c);//3
unsigned int : -56u
补码:
00000000 00000000 00000000 00111000 (56)
11111111 11111111 11111111 11000111 (取反)
11111111 11111111 11111111 11001000 (-56的补码)
00000000 00000000 00000000 00000011 >> 30
int =>char
00000011
char =>int
END