目录
一.思维导图
二.算术操作符
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 除法(取余) |
1. 除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于/操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法(有一个及以上均可认为是浮点数操作)。
int main() { int a = 7 / 2; printf("%d\n", a); double b = 7 / 2; printf("%lf\n", b); int c = 7.0 / 2; printf("%d\n", c); double d = 7.0 / 2; printf("%d\n",d ); return 0; }
3. %操作符的两个操作数必须为整数。返回的是整除之后的余数。
int main() { int a = 7 / 3; printf("%d\n", a); int b = 7 % 3; printf("%d\n", b); return 0; }
4.除数不可以为0
三.移位操作符
<<左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
注:左移或右移,移动的都是变量中的二进制信息
注:整数在内存中存放的是补码,计算也是按照补码来进行计算的
int main() { int a = 15; //00000000000000000000000000001111 - 原码 //00000000000000000000000000001111 - 反码 //00000000000000000000000000001111 - 补码 int b = -15; //10000000000000000000000000001111 - 原码(第一位是符号位,1表示负,0表示正) //11111111111111111111111111110000 - 反码(原码符号位不变,其余按位取反) //11111111111111111111111111110001 - 补码(反码+1就是补码) return 0; }
//移位移动的是补码的二进制序列 int main() { int a = 15; int b = a >> 1; printf("%d\n", a); printf("%d\n", b); return 0; }
运行结果:二进制1111是15,二进制111是7
四.位操作符
& 按位与,对应二进制位有0则为0,两个同时为1才是1
int main() { int a = 3; //00000000000000000000000000000011 -补码 int b = -5; //10000000000000000000000000000101 //11111111111111111111111111111010 //11111111111111111111111111111011 -补码 int c = a&b; //&---对应二进制位有0则为0,两个同时为1才是1 //00000000000000000000000000000011 //11111111111111111111111111111011 //00000000000000000000000000000011---c补码 printf("%d\n", c); return 0; }
通过对于C的补码分析,我们得出C应该为3,代码运行结果也是3
| 按位或,对应二进制位有1则为1,两个同时为0才是0
int main() { int a = 3; //00000000000000000000000000000011 -补码 int b = -5; //10000000000000000000000000000101 //11111111111111111111111111111010 //11111111111111111111111111111011 -补码 int c = a|b; //|---对应二进制位有1则为1,两个同时为0才是0 //00000000000000000000000000000011 //11111111111111111111111111111011 //11111111111111111111111111111011---c补码 //11111111111111111111111111111010 //10000000000000000000000000000101--- -5 printf("%d\n", c); return 0; }
^ 按位异或
int main() { int a = 3; //00000000000000000000000000000011 -补码 int b = -5; //10000000000000000000000000000101 //11111111111111111111111111111010 //11111111111111111111111111111011 -补码 int c = a^b; //^---对应二进制位相同为0,相异为1 //00000000000000000000000000000011 //11111111111111111111111111111011 //11111111111111111111111111111000---c补码 //11111111111111111111111111110111 //10000000000000000000000000001000--- -8 printf("%d\n", c); return 0; }
注:他们的操作数必须是整数,操作的是二进制位
一个小例子:
不能创建临时变量(第三个变量),实现两个数的交换
//不能创建临时变量(第三个变量),实现两个数的交换。 //当数特别大的时候不行的一个办法 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; }
能解决所有问题的方法:
a^a -> 0
a^0 -> a
a^b^a = a^a^b(异或 支持交换律)
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; }
五.赋值操作符
复合赋值符 += ,-= , *=, /=, %=, >>=, <<=, &=, |=, ^=
int x = 10;
x = x+10;
x += 10;//复合赋值
//其他运算符一样的道理。这样写更加简洁。
六.单目操作符
! | 逻辑反操作 |
- | 负值 |
+ | 正值 |
& | 取地址(取出某个变量的地址) |
sizeof | 操作数的类型长度(以字节为单位) |
~ | 对一个数的二进制按位取反 |
-- | 前置、后置-- |
++ | 前置、后置++ |
* | 间接访问操作符(解引用操作符,通过指针变量存放的地址,找到指向的空间,内容) |
(类型) | 强制类型转换 |
!举例
int main() { int flag = 5; if (flag == 0) { printf("1\n"); } if (!flag)//若flag为假,!flag为真,打印2 { printf("2\n"); } if (flag) { printf("3\n"); } return 0; }
运行结果:
sizeof 求变量(类型)所占空间的大小。
sizeof不是函数,是操作符。计算的是类型创建变量的大小,单位是字节
int main() { int a = -10; int* p = NULL; printf("%d\n", !2); printf("%d\n", !0); a = -a; p = &a; printf("%d\n", sizeof(a)); printf("%d\n", sizeof(int)); return 0; }
++和--的前置后置
前置:先自增/自减,再赋值
int main() { int a = 10; int x = ++a; //先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。 //a = a+1 =11,x=a=11 int y = --a; //先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10; //a = a-1=11-1 =10,y = a=10 return 0; }
运算结果:
后置:先赋值,再自增/自减
int main() { int a = 10; int x = a++; //先对a先使用,再增加,这样x的值是10;之后a变成11; //x = a = 10,a = a+1 = 11 int y = a--; //先对a先使用,再自减,这样y的值是11;之后a变成10; //y =a = 11,a = a-1 printf("x =%d y =%d", x,y ); return 0; }
运算结果:
七.关系操作符
> ,>= ,< ,<=, !=(用于测试“不相等”),==(用于测试“相等”)
注:在编程的过程中== 和=不小心写错,导致的错误。
八.逻辑操作符
&& 逻辑与(并且)
|| 逻辑或(或者)
int main() { int a = 0; int b = 5; scanf("%d %d", &a, &b); //a和b都是5,打印1 if (a == 5 && b == 5) { printf("1\n"); } //a或者b都是5,打印0(只要有1个是5即可) if (a == 5 || b == 5) { printf("0\n"); } return 0; }
观察代码,我们可以判断,当a和b都是5,打印1;a或者b都是5,打印0(只要有1个是5即可),输入3 5 ,我们来看看运行结果:
九.条件操作符(三目操作符)
exp1 ? exp2 : exp3
exp1 exp2 exp3 真 执行 不执行 假 不执行 执行
十.逗号表达式
exp1, exp2, exp3, …expN
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
十一.下标引用、函数调用和结构成员
1. [ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
int arr[10];//创建数组 arr[9] = 10;//实用下标引用操作符。
在上面的代码案例中,[ ]的两个操作数是arr和9。
2. ( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
对于函数调用操作符来说,最少有1个操作数(函数可以没有参数)
如下面main函数来说,
test1()的操作数是函数名test1
test2()的操作数是函数名test2和“hello”
void test1() { printf("1\n"); } void test2(const char* str) { printf("%s\n", str); } int main() { test1(); //实用()作为函数调用操作符。 test2("hello");//实用()作为函数调用操作符。 return 0; }
3. 访问一个结构的成员
. 结构体.成员名 -> 结构体指针->成员名 struct Book { //三个成员 char name[30]; char author[20]; float price; }; int main() { struct Book b1 = { "书名1","作者1",66.5f };//书1 struct Book b2 = { "书名2","作者2",21.5f };//书2 //结构体变量.成员名 //打印b1内容 printf("%s %s %.1f\n", b1.name ,b1.author,b1.price); //打印b2内容 printf("%s %s %.1f\n", b2.name, b2.author, b2.price); return 0; }
运行结果: