1.操作符介绍
2.表达式求值
操作符分类
- 算术操作符
- 移位操作符
- 位操作符
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 条件操作符
- 逗号操作符
- 下标引用,函数调用和结构体成员
1.算术操作符
+ - * / %
除 % 以外其余操作符均可作用于整数和浮点数
2. 移位操作符
<< 左移操作符
>> 右移操作符
只能作用于整数
移动的是二进制位
整数的二进制表示有三种:原码,反码,补码
存储到内存的是补码,打印的形式是原码
》 右移操作符:
1.算术右移右边丢弃,左边补原符号位(当前编译器下通常是算术右移)对于正整数有除2的效果
2.逻辑右移
右边丢弃,左边补0
《 左移操作符
左边丢弃,右边补0
对于正整数 左移有乘2的效果
3. 位操作符
& 按位与 /二进制数相同为1
| 按位或 / 二进制数只要有1则都为1
^ 按位异或 /二进制位相同为0 相异为1
**操作数必须是整数**
编写代码,交换两个数值,不能使用临时变量。
异或
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("a = %d b = %d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d b = %d\n", a, b);
return 0;
}
总结:
5^5=0 ->a^a=0;
0^5=5 ->0^a=a;
异或操作符支持交换律
3^3^5 = 5;
3^5^3 = 5;
统计二进制中1的个数
#include<stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);//num=3 00000000000000000000000000000011
int count = 0;// 1 00000000000000000000000000000001
int i = 0;// num&1 00000000000000000000000000000001
for (i = 0; i < 32; i++)
{
if (1 == ((num >> i) & 1))
count++;
}
printf("%d\n", count);
return 0;
}
5. 单目操作符
双目操作符 两个操作数
eg: a+b
单目操作符 只有一个操作数
! 逻辑反操作
& 取地址
sizeof 操作数的类型长度
~ 对一个数的二进制(补码)按位取反
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
-- 前置,后置
++ 前置,后置
sizeof 和数组
#include<stdio.h>
void Print1(int arr[])
{
printf("%d\n", sizeof(arr));
}
void Print2(char ch[])
{
printf("%d\n", sizeof(ch));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(ch));
Print1(arr);
Print2(ch);
return 0;
}
sizeof是操作符,用于计算变量所占空间的大小,单位字节
这里可能会有疑问,为什么整型指针和字符指针的大小是一样?
很好理解,因为指针的大小不会因为类型不同而有所变化
strlen是库函数,是用来求字符串长度
按位取反 ~
6. 关系操作符
>
>=
<
<=
!= 不等于
== 等于
这里需要区分 == 和 =,编写过程若写错,会导致一定的错误。
7 .逻辑操作符
&& 逻辑与
同时为真(非零) 则为1
1&&2-------》1
1&&0-------》0
|| 逻辑或
同时为假(零)则为零
1||0--------》1
0||0--------》0
8. 条件操作符
exp1?exp2:exp3
若exp1为真,则执行exp2,否则执行exp3
9. 逗号表达式
逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);//a=12 b=13 13赋值给c
printf("c= %d\n", c);
return 0;
}
10. 下标引用,函数调用和结构成员
1.[ ]下标引用操作符
操作数:一个数组名+一个索引值
arr[5]=10
[ ]的两个操作数是arr和5
2.( )函数调用操作符
接受一个或多个操作数:第一个操作数是函数名,其余操作数是传递的参数
至少有一个操作数->函数名
3.访问一个结构的成员
结构体 . 成员名
结构体指针->成员名
表达式求值
表达式求值的算术运算一部分由操作符的优先级和结合性决定
隐式类型转换
C的整型算术运算总是至少以默认整型类型的精度来进行
字符和短整型操作数在运算前需要转换成整型,这种转换称为整型提升
如何进行整型提升呢
//负数的整型提升
char a = -1;
原码:10000001
反码:11111110
补码:11111111
因为char 为有符号的字符
整型提升时,高位补充符号位
提升后的结果
补码:11111111111111111111111111111111
//整数的整型提升
char b = 1;
原码==反码==补码:00000001
因为char 为有符号的字符
整型提升时,高位补充符号位
提升后的结果
原码==反码==补码:00000000000000000000000000000001
算术转换
操作符的属性
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序
对于是否控制求值顺序只有
逻辑操作符,条件操作符
因为这两类操作符都需要判断真假