一、算术操作符
+ - * / %
(1)算术操作符是我们从小到大数学中经常用到的操作符,加、减、乘、整除、取余(取模)。
(2)/:即两个实数相除的结果是双精度实数,两个整数相除的结果是整数(商)。
(3)%:两个操作数必须为整数,返回整除之后的余数,余数也为整数。除%以外的运算符的操作数都可以是任何算术类型。
二、移位操作符
>> <<
(1)>>右移操作符 <<左移操作符。
(2)这里的移位是指移二进制位。
(3)我们这里以左移操作符为例,由于右移操作符涉及到最高符号位知识,后期再深入讲解。
int main() { int a = 6; int b = a << 1; // 左移操作符,移动二进制位 // a=6 // 00000000000000000000000000000110 (32bit位) 6的2进制表示 // 00000000000000000000000000001100 每一个二进制位向左移动,右边自动补0 // b=12 得到结果的十进制为12 printf("%d\n", b); printf("%d\n", a); // a的值不变,类似b=a+1,a的值也没变 return 0; }
三、位操作符
& ^ |
(1)这里的位操作符都是指的二进制位。
(2)&按位与:按2进制位与 - 只要有0则为0。
int main() { int a = 3; int b = 5; // 按位与 // 00000000000000000000000000000011 - (a=3) // 00000000000000000000000000000101 - (b=5) // 00000000000000000000000000000001 - 结果为1 int c = a & b;//1 printf("%d\n", c); return 0; }
(3)^按位异或:按2进制位异或 - 相同为0,相异为1。
int main() { int a = 3; int b = 5; // 按位异或 // 00000000000000000000000000000011 // 00000000000000000000000000000101 // 00000000000000000000000000000110 int c = a ^ b;//结果为十进制6 printf("%d\n", c); return 0; }
(4)|按位或:按2进制位或 - 只要有1则为1。
int main() { int a = 3; int b = 5; // 按位或 // 00000000000000000000000000000011 // 00000000000000000000000000000101 // 00000000000000000000000000000111 int c = a | b;//结果为7 printf("%d\n",c); return 0; }
(4)注意位操作符的操作数都为整数。
四、赋值操作符
= += -= /= &= ^= |= >>= <<=
(1)=为赋值符,+= -= /= &= ^= |= >>= <<=为复合赋值符。
int main() { int a = 10; // 创建变量a,并且初始化为10 a = 20; // 赋值(已经创建变量才叫赋值,上面叫初始化) // 下面两种写法含义相同,得到的结果相同 a = a + 10; // 赋值 a += 10; // 复合赋值符 // 同理,其他复合赋值符用法也类似 return 0; }
五、单目操作符
! 逻辑反操作 - 负值 + 正值 & 取地址 sizeof 操作数的类型长度(以字节为单位) ~ 对一个数的二进制按位取反 -- 前置、后置-- ++ 前置、后置++ * 间接访问操作符(解引用操作符) (类型) 强制类型转换
(1)单目操作符指只有一个操作数;a+b中的+有两个操作数,所以为双目操作符。
(2)!逻辑反操作:表达式的值有真假——0为假,非0为真;我们使用!可以让表达式条件真变为假,假变为真。
// 真和假 // 非0就是真 5 - 真 // 0就是假 0 - 假 int main() { int a = 10; printf("%d\n", !a); // 打印结果为0 int b = 0; printf("%d\n", !b); // 打印结果为1,非0的数很多,我们规定!0为1 return 0; }
// 实际中用法 if (a) // a为真,要进入if语句 { } if (!a) // a为假,要进入if语句 { }
(3)这里的-、+不是减和加的意思,而是负值与正值的意思,因此这里是单目操作符。
int main() { int a = 10; int b = -a; // 负值 int c = +a; // 正值,一般省略掉 return 0; }
(4)&取地址操作符涉及到指针的概念,后面讲解。
(5)sizeof是操作符,不是函数,计算该类型所占内存空间的大小,单位是字节。
int main() { int a = 10; printf("%d\n", sizeof(a)); // 操作数只有一个(以字节为单位) printf("%d\n", sizeof(int)); return 0; }
(6)~按(二进制)位取反,涉及到原码反码补码的概念,并不只是单纯的把0换为1,1换为0那么简单。
// ~对一个数的二进制位按位取反 // 整数在内存中存储的时候,存储的是二进制 // 一个整数的二进制表示有3种形式: // 原码 // 反码 // 补码 // 正整数:原码、反码、补码相同 // 负整数:原码、反码、补码是需要计算的 // 有符号的整数:最高位是0,表示正整数;最高位是1,表示负整数 // int a = 1; // 4个字节 - 32bit // 00000000000000000000000000000001 - 原码 // 00000000000000000000000000000001 - 反码 // 00000000000000000000000000000001 - 补码 // int a = -1; // 10000000000000000000000000000001 - 原码 // 11111111111111111111111111111110 - 反码(原码的符号位不变,其他位按位取反,得到反码) // 11111111111111111111111111111111 - 补码(反码的二进制序列+1就是补码) // 内存中存储整数的时候,存储的是二进制的补码,打印的是原码 // 计算的时候采用的也是补码 int main() { int a = 0; // 可以理解0为正数 // 00000000000000000000000000000000 - 0在内存中的补码 // 11111111111111111111111111111111 - 补码按位取反,得到存储在计算机内的补码 // 11111111111111111111111111111110 - 反码 // 10000000000000000000000000000001 - 原码(-1) printf("%d\n", ~a); // 最后结果是-1,不是非常大的数字 return 0; }
(7)--与++,意义就是让操作数自增1,但是在某些情况下有前置和后置的区别。
前置是先计算后使用,后置是先使用后计算。
// 以--为例,++类似 int main() { int a = 2; int c = --a; // 先减减,后使用,a=1,c=1 printf("%d\n", a); // 1 printf("%d\n", c); // 1 }
// 以--为例,++类似 int main() { int a = 2; int c = a--; // 先使用,后减减,a=1,c=2 printf("%d\n", a); // 1 printf("%d\n", c); // 2 }
(8)*解引用操作符涉及到指针的概念,后面讲解。
(9)强制类型转换,写代码中尽量不要使用。
int main() { // int a = 3.14; 3.14默认双精度浮点数赋值给int型变量会导致精度丢失,编译器会出现警告 int a = (int)3.14; // 为了不让警告出现,可以采用强制类型转换 printf("%d\n", a); return 0; } // (类型名)(表达式) // 表达式和类型名都应该用括号括起来 // 例如: // (double)a——(将a转换成double类型) // (int)(x + y)——(将x + y的值转换成int型) // (float)(5 % 4)——(将5 % 3的值转换成float型)
六、关系操作符
> >= < <= != ==
(1)关系操作符,用于比较表达式的大小关系。
(2)!=用于测试“不相等”;==用于测试“相等”。
(3)注意判断相等是==;=是赋值操作符。
七、逻辑操作符
&& ||
(1)&& - 逻辑与 - 并且(两个条件都满足才可以)。
int main() { int a = 3; int b = 5; // 如果a==3并且b==4,打印哈哈 if ((a == 3) && (b == 4)) { printf("哈哈\n"); // 有一个条件为假,不打印 } return 0; }
(2)|| - 逻辑或 - 或者(有一个满足条件就可以)。
int main() { int a = 3; int b = 5; // 如果a==3或者b==4,打印呵呵 if ((a == 3) || (b == 4)) { printf("呵呵\n"); // 有一个条件为真,打印呵呵 } return 0; }
八、条件操作符
exp1 ? exp2 : exp3
(1)条件操作符也叫三目操作符,有三个操作数。
(2)我们首先看下面下面代码
int main() { int a = 10; int b = 0; if (a == 5) { b = -6; } else { b = 6; } return 0; }
该代码可以用条件操作符进行简化
int main() { int a = 10; int b = 0; b = (a == 5 ? -6 : 6); return 0;
因此条件操作符的使用规律为如果exp1成立执行exp2,否则执行exp3。
九、逗号表达式
exp1, exp2, exp3, …,expN
(1)逗号表达式:由逗号隔开的一串表达式,日常写代码应用较少。
int main() { int a = 0; int b = 3; int c = -1; // , - 逗号表达式 // 逗号表达式会从左向右依次计算 // 整个逗号表达式的结果是最后一个表达式的结果 int d = (a = b - 5, b = a + c, c = a + b, c -= 5); // a=-2,b=-3,c=-10,最后表达式结果为-10赋值给d printf("%d\n", d); return 0; }
十、下标引用、函数调用和结构成员
[ ] ( ) . ->
(1)[ ]下标引用:操作数为一个数组名+一个索引值。
int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // 这里数组定义的[]不是操作符 // 0~9 arr[9]; // 下标引用操作符 两个操作数arr 9 }
(2)函数调用操作符( ):接受一个或多个操作数,第一个操作数是函数名,剩余的操作数就是传递给函数的参数,因此操作数不确定。
int Add(int x, int y) { return x + y; } int main() { int ret = Add(3, 5); // 函数调用操作符的操作数不确定,函数名+参数个数 printf("hehe\n"); // ()函数调用操作符printf() return 0; }
(3).和->涉及到指针的概念,后面讲解。
本篇除了. -> & *这四个操作符都大体介绍了一遍,请读者多多理解。