算术操作符
+ - * / %
这几个操作符都比较简单,需要注意的是,+-*/这几个操作符可以用于整数和浮点数。%这个操作符的两个操作数只能为整型。
在程序中,若是两个操作数都是整型,那么得到的结果也只能是整型,编译器会自动截断后面的小数部分。若是某个操作数为浮点型,那么结果只能为浮点型。
移位操作数
左移操作数:<<
左移规则:将数字在内存中的二进制表示左移一位,右边补0, 等同于将变量中的数本身乘以2并且将值重新赋给变量。
#define _CRT_SECURE_NO_WARNINGS //添加头文件 #include <stdio.h> #include <stdlib.h> //主函数,函数入口 int main() { int num = 10; //未移位前:00000000000000000000000000001010 printf("%d\n", num << 1);//打印20 //左移一位后:00000000000000000000000000010100 return 0; }
右移操作数:>>
右移规则:
①逻辑右移:移位操作后,左边用零填充,右边舍弃。
②算术右移:移位操作后,左边根据操作数的正负来确定用0/1来填充,右边舍弃。
#define _CRT_SECURE_NO_WARNINGS //添加头文件 #include <stdio.h> #include <stdlib.h> //主函数,函数入口 int main() { int num = -1; //右移位前:11111111111111111111111111111111 //右移移位后:11111111111111111111111111111111 //打印-1 printf("%d\n", num >> 1); return 0; }
移位操作相当于是对数据乘以二的n次方或者除以二的n次方,例如,左移4位,相当于是对数据乘以2的四次方;
但是由于移位操作是直接作用于二进制代码的,是直接作用在机器指令上的,所以它的运算速度比普通乘除要快许多;
不过,虽然运算速度快,但是在写代码的时候尽量避免使用移位操作符,因为①:会影响可读性,相对于一般的项目,完成项目的效率可要比代码最终的执行效率重要太多了;
②:现在一些高级的编译器,会将你代码中的乘除操作自动转换为移位操作,还是比较人性化的。
位操作符
位操作符是作用在二进制代码的每一位上
按位与:&;1&1为1,其余均为0;
例:(1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
(2)取一个数中指定位,方法:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。
#define _CRT_SECURE_NO_WARNINGS //添加头文件 #include <stdio.h> #include <stdlib.h> int BitOneCount(int num) { int count = 0; //一个整形最多有32位,因此我们需要从第一位开始进行32个循环逐步计数 for (int i = 0; i < 32; i++) { //右移验证最低位是否是1,是1则计数器+1 if (num >> i & 1 != 0) { count++; } } return count; } //主函数,函数入口 int main() { printf("%d\n", BitOneCount(-1));//打印32 return 0; }
按位或:|;0|0为0,其余均为1;
例:(1)常用来对一个数据的某些位置1,方法:找到一个数,对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或可使X中的某些位置1。
按位异或:^;两操作数相同为0,不同为1;
例:(1)使特定位翻转,要使哪几位翻转就将与其^运算的该几位置为1即可。
(2)使特定位保留,因为原数中的1与0进行^运算得1,0^0得0,故保留原数。
(3)交换两个值,不用临时变量,
假如a=3,b=4,想将a和b的值互换,可以用以下赋值语句实现:a=a^b;b=b^a;a=a^b;
原理:①执行前两个赋值语句:“a=a^b;”和“b=b^a;”相当于b=b^(a^b)。而b^a^b等于a^b^b。b^b的结果为0,因为同一个数与本身相^,结果必为0。因此b的值等于a^0,即a,其值为3。
②再执行第三个赋值语句:a=a^b。由于a的值等于(a^b),b的值等于(b^a^b),因此,相当于a=a^b^b^a^b,即a的值等于a^a^b^b^b,等于b。
(4)快速判断两个值是否相等
举例1: 判断两个整数a,b是否相等,则可通过下列语句实现: return ((a ^ b) == 0);
按位取反:~;1变0,0变1;
赋值操作符
赋值运算符:=;这是最常见的,这代表了赋值的意思,并不是判断相等的,一定要注意这一点,一不小心就搞错了。
赋值操作符还有一些变形操作:
a+=1相当于a=a+1 a*=2相当于a=a*2
单目操作符
逻辑反:!;此操作符可以将逻辑语句进行取反操作。
负值/正值:-/+;此操作符与加减不同,可以将数值取到对应的相反数;
取地址:&;可以将变量在内存中的地址取到,scanf()操作的时候就是在取地址;在指针操作中也会经常会见到;
sizeof:sizeof();可以求出变量在内存中所占字节的大小;
自增/自减:++/--;一个变量的自增自减相当于是,将这个数减一或加一再赋给这个这个变量;需要注意的是前置与后置的区别:前置:先加加或减减之后,再使用;
后置:先使用,然后加加或减减;
这里以++的前置和后置为例:
#include<stdio.h> #include<stdlib.h> int main() { int a = 1; int b = 2; b = a++; printf("%d %d\n", a, b); //输出结果:a=2;b=1; int c = 2; int d = 4; d = ++c; printf("%d %d\n", c, d); //输出结果:c=3;d=3; return 0; }
解引用:*;这个操作符常与指针连用,可以通过解引用指针找到指针所指变量中的数据;
强制类型转换:(类型);若一个变量定义的类型无法满足某个表达式时,就可使用此操作符来实现目的。
关系操作符
关系操作符是用来判断表达式的逻辑关系的,若满足表达式,则为真;若表达式不满足,则为假。
//大于 > //大于等于 >= //小于 < //小于等于 <= //等于 == //不等于 !=
逻辑操作符
此操作符用来实现一个逻辑表达式的连接
逻辑与:&&;前后表达式都为真才为真,否则为假
逻辑或:||;前后表达式满足一个即为真,若都为假,才为假
条件操作符
也叫作三目运算符,具体形式如下:
表达式 1 ? 表达式 2 : 表达式 3;
含义:若表达式1为真,则实行表达式2;若为假,则执行表达式3;相当于是if语句的用法,但是比if更简便,更灵活。
逗号表达式
表达式1, 表达式2, 表达式3...表达式n;
顺次执行每一个表达式,而这个总的表达式的值看的是最后一个表达式。
下标引用
数组名[下标];
数组名[下标],可以访问数组中的对应下标的数据;
函数表达式
函数名(参数);
函数调用十分简单,只需写出如上形式即可,参数可有而无;
结构体成员
.
->
上面形式中,第一个是在结构体变量中可以取得到结构体的成员;第二个是在结构体指针中取得结构体成员。
表达式求值
隐式类型转换:
//负数的整形提升 char c1 = -1; 变量c1的二进制位(补码)中只有8个比特位: 1111111 因为 char 为有符号的 char 所以整形提升的时候,高位补充符号位,即为1 提升之后的结果是: 11111111111111111111111111111111 //正数的整形提升 char c2 = 1; 变量c2的二进制位(补码)中只有8个比特位: 00000001 因为 char 为有符号的 char 所以整形提升的时候,高位补充符号位,即为0 提升之后的结果是: 00000000000000000000000000000001 //无符号整形提升,高位补0
//实例1 int main() { char a = 0xb6; short b = 0xb600; int c = 0xb6000000; if(a==0xb6) printf("a"); if(b==0xb600) printf("b"); if(c==0xb6000000) printf("c"); return 0; }
算数转换:
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作 就无法进行。下面的层次体系称为寻常算术转换:
long double double float unsigned long int long int unsigned int int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
警告:
float f = 3.14; //隐式转换,会有精度丢失 int num = f;
但是算术转换要合理,要不然会有一些潜在的问题。
操作符属性
复杂表达式的求值有三个影响的因素:
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序
操作符的优先级:

浙公网安备 33010602011771号