一、操作符分类:
(操作符也是运算符)
算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下标引用、函数调用和结构成员
二、算术操作符
- + * / %
int main()
{
// / 除法 - 得到的是商
// 除法操作符的两个操作数都是整数的话,执行的是整数除法
// 除法操作符的两个操作数只要有一个浮点数,执行的是小数除法
//
// % 取模(取余)得到的是余数
// 取模操作符的操作数必须是整数
printf("%lf\n", 10 / 3.0);//5
printf("%d\n", 10 % 2);//0
return 0;
}
总结:
- 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
- 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
- % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
三、移位操作符
(移动的是二进制的位)
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
int a = -5;
查看整数在内存中存储的补码是什么:
4个二进制位表示一个16进制位
1.左移操作符
b=a<<1
a自身的值不会变化
int main()
{
int a = -3;
//10000000000000000000000000000011
//11111111111111111111111111111100
//11111111111111111111111111111101 - 补码
//
int b = a << 1;
//11111111111111111111111111111010
//11111111111111111111111111111001
//10000000000000000000000000000110
//11111111111111111111111111111010
//10000000000000000000000000000101
//10000000000000000000000000000110
printf("%d\n", b);//-6
printf("%d\n", a);//-3
return 0;
}
2.右移操作符
右移运算分两种:
- 逻辑移位
左边用0填充,右边丢弃- 算术移位
左边用原该值的符号位填充,右边丢弃
常见采用算术右移
注意:
对于移位运算符,不要移动负数位,这个是标准未定义的。
int num = 10;
num>>-1;//error
四、位操作符
& //按位与
| // 按位或
^ //按位异或
注:他们的操作数必须是整数。
int main()
{
int a = 3;
int b = -5;
int c = a ^ b;//按位异或 - 对应的二进制位,相同为0,相异为1
11111111111111111111111111111011 - -5的补码
00000000000000000000000000000011 - 3的补码
11111111111111111111111111111000
11111111111111111111111111110111
10000000000000000000000000001000
int c = a | b;//按位或
11111111111111111111111111111011 - -5的补码
00000000000000000000000000000011 - 3的补码
11111111111111111111111111111011
int c = a & b;//按位与
00000000000000000000000000000011 - 3的补码
10000000000000000000000000000101
11111111111111111111111111111010
11111111111111111111111111111011 - -5的补码
00000000000000000000000000000011 - 3的补码
00000000000000000000000000000011
printf("%d\n", c);
return 0;
}
小题一道
不能创建临时变量(第三个变量),实现两个数的交换
a^a = 0
0^a = a
3^ 3^ 5 = 5
3^ 5^ 3 = 5
int main()
{
int a = 3;
int b = 5;
printf("交换前:a=%d b=%d\n", a, b);
方法3:
a = a ^ b;
b = a ^ b;
a = a ^ b;
方法2:(a和b加起来可能会超出整形大小)
a = a + b;
b = a - b;
a = a - b;
方法1:(不满足要求)
int tmp = 0;
tmp = a;
a = b;
b = tmp;
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
五、赋值操作符
赋值操作符可以连续使用,比如:
int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值
这样的代码感觉怎么样?
那同样的语义,再看看:
x = y+1;
a = x;
这样的写法是不是更加清晰且易于调试。
复合赋值符
+=
-=
*=
/=
%=
<<=
.>> =
&=
|=
^=
int x = 10;
x = x+10;
x += 10;//复合赋值
//其他运算符一样。这样写更加简洁。
六、单目操作符
单目操作符介绍
// ! 逻辑反操作
// - 负值
// + 正值
// & 取地址
// sizeof 操作数的类型长度(以字节为单位)
// ~ 对一个数的二进制按位取反
// – 前置、后置–
// ++ 前置、后置++
// * 间接访问操作符(解引用操作符)
// (类型) 强制类型转换
// !
int main()
{
int flag = 5;
if (flag)//flag为真做什么
{
}
if (!flag)//flag为假做什么
{
}
return 0;
}
// *
int main()
{
int a = 10;
int* p = &a;//&取地址操作符
*p = 20;//解引用操作符(间接访问操作符)
//int arr[10];
//&arr;//取出数组的地址
return 0;
}
// sizeof
int main()
{
int a = 10;
printf("%d\n", sizeof a);
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
int arr[10] = { 0 };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr[0]));
int sz = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz);
return 0;
}
错误案例:
int main()
{
int a = 3;
a = 10;
a + 3 = 15;//err
return 0;
}
// ~
int main()
{
int a = 0;
//00000000000000000000000000000000
//11111111111111111111111111111111
//11111111111111111111111111111110
//10000000000000000000000000000001
//
printf("%d\n", ~a);
return 0;
}
结合使用
int main()
{
int a = 3;
//00000000000000000000000000000011
//00000000000000000000000000001000
a |= (1 << 3);
printf("%d\n", a);
//00000000000000000000000000001011
//11111111111111111111111111110111
a &= (~(1 << 3));
printf("%d\n", a);
return 0;
}
前置++和后置++
int main()
{
int a = 10;
//int b = --a;//前置--,先--,后使用
int b = a--;//后置--,先使用,后--
printf("a=%d b=%d\n", a, b);
//printf("%d\n", ++a);//前置++,先++,后使用
//printf("%d\n", a);
//int b = a++;//后置++,先使用,再++
//int b = a,a=a+1;
//printf("a=%d b=%d\n", a, b);
return 0;
}
强制类型转换是一种临时的状态
int main()
{
float a = 3.14f;
int b = (int)a;
a还是float类型
//int b = int(a);//err
return 0;
}
sizeof和数组
#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));//(4)
}
int main()
{
int arr[10] = {0};
char ch[10] = {0};
printf("%d\n", sizeof(arr));//(1)
printf("%d\n", sizeof(ch));//(3)
test1(arr);
test2(ch);
return 0;
}
(1)、(2)两个地方分别输出多少? 40 4
(3)、(4)两个地方分别输出多少? 10 4
七、关系操作符
// >
// >=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
注意==和=不要写错
八、逻辑操作符
int main()
{
int a = 3 && 5;
a = 1 或者 0 因为真为1假为0
printf("%d\n", a);// 1
int a = 0 || 0;//1 0
printf("%d\n", a);// 0
return 0;
}
习题1:
结果1 2 3 4
习题2:
结果2 3 3 5
习题3:
结果2 2 3 4
习题4:
结果1 3 3 4