操作符分类
1. 算术操作符
2. 移位操作符
3. 位操作符
4. 赋值操作符
5. 单目操作符
6. 关系操作符
7. 逻辑操作符
8. 条件操作符
9. 逗号表达式
10. 下标引用、函数调用和结构成员
算术操作符
+ - * / %
对于%操作符只适用于整数类型,其他操作符既适用与整数类型,有适用与浮点数
移位操作符
注:不要移动负数位,这个是标准未定义
1.左移操作符
操作规则:左边丢弃,右边补零
2.右移操作符
操作规则:
1.逻辑移位:左边用0补充,右边丢弃
2.算术移位:左边用原该值的符号位补充,右边丢弃
3.例题
不使用(a+b) /2这种方式,求两个数的平均值
#include<stdio.h>
int main()
{
int a = 10;
int b = 30;
int avg = 0;
avg = (a + b) >> 1; //右移一位相当于除以2
printf("%d/n", avg);
return 0;
}
总结:对于正整数,左移一位,就是将数值乘2;右移一位就运算数值除2;
但是位操作的效率要比运算符高。
位操作符
& | ^
注:操作数必须是整数
例题:
1.一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的,请找出这个数字(使用位运算)
#include<stdio.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int tem = 0;
for (i = 0; i <sz; i++)
{
tem = tem^arr[i];
//0与第一个数异或,遇到下一个相同的数异或时消掉原来的数
}
printf("%d \n", tem);
return 0;
}
2.不创建临时变量(第三个变量),实现两个数的交换
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;
a = a^b;
printf("a = %d b = %d\n", a, b);
return 0;
}
总结:一个数和另一个数异或两次得到的还是原来的数。
3.统计一个整数中二进制位上1的个数。
int fun(int num)
{
int count = 0;
while (num)
{
num = num & (num - 1);
++count;
}
return count;
}
总结:n & (n - 1)将整数n的最后一位为1的位变成0
4.统计一个整数中二进制位上1的个数。
int fun(int num)
{
int count = 0;
while(num)
{
n -= n & (~n + 1);
++count;
}
return count;
}
总结:n & (~n + 1)提取出整数n最后一位为1的数。
4..不使用+,-,*,/完成整数相加
int Add(int num1, int num2)
{
int sum, carry;
do{
//将两个数异或,模拟加法中相加不进位的结果
sum = num1 ^ num2;
//只考虑进位的情况
carry = (num1 & num2) << 1;
num1 = sum;
num2 = carry;
}
while(num2 != 0); //将结果相加的过程就重复上述过程,直到进位为0
return sum;
}
赋值操作符
只要是出现表达式的地方,都允许进行赋值,下面的语句:
x = y = a + 5;
赋值操作符的结合性(求值的顺序)是从左到右,所以这个表达式相当于:
y = a +5;
x = y;
复合操作符
+= -= *= /= %=
<<= >>= &= ^= |=
int x = 10;
x = x+10;
x+=10; //复合赋值
// 其他运算符一样的道理,这样写更为简洁
单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置 --
++ 前置、后置 ++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
例题:
++和--运算符:
#include <stdio.h>
int main()
{
//前置++和--
int a = 10;
int x = ++a;
//先对a自增,再对a进行表达式求值,a = 11, x = 11;
int b = 10;
int y = --b;
//先对b自减,再对吧进行表达式求值,a = 9, x = 9;
//后置++和--
int c = 10;
x = c++;
//对a先使用,再自增,c = 11, x = 10;
int d = 10;
y = d--;
//对d先使用,再自减,d = 9, y = 10
return 0;
}
关系操作符
> >= < <= != ==
注:不要吧判断用的 == 和 赋值用的 = 搞混了
逻辑操作符
&& 逻辑与
|| 逻辑或
例题:
#include<stdio.h>
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++&&++b&&d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
// 输出结果: 1 2 3 4
#include<stdio.h>
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
// 输出结果: 1 3 3 4
条件操作符
expression1 ? expreession2 : expression3
首先计算expresion1,如果值为真,整个表达式的值就是expreession2的值,expreession3不进行求值。
但是,如果expreession1的值为假,那么整个条件语句的值就是expreession3的值,expreession2不进行求值。
逗号操作符
expression1,expression2,expression3,……,expressionN
逗号表达式,从左往右依次执行,整个表达式的结果就是最后一个表达式的结果。
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = (a>b, a = b + 10, a, b = a + 1);
printf("%d\n", c);
}
// 输出结果:13
下标引用、函数调用和结构成员
1.下标引用操作符
[ ]
操作数:一个数组名 + 一个索引值
array[ 下标 ]
*( array + ( 下标 ) )
2.函数调用操作符
( )
接受一个或多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数
3.访问一个结构的成员
. 结构体 . 成员名
-> 结构体指针 -> 成员名