系列文章目录
第一章 “C“浒传——初识C语言(更适合初学者体质哦!)
第二章 详细认识分支语句和循环语句以及他们的易错点
第三章 初阶C语言——特别详细地介绍函数
第四章 初始C语言——详细地讲解数组的内容以及易错点
第五章 初始C语言——详细讲解操作符以及操作符的易错点
目录
前言
一、操作符分类
为什么要学习操作符?是为了进行表达式求值。在学习操作符之前,先跟着小编进行学习操作符的分类吧!
二、算术操作符(两个操作数)
在这一部分,小编认为没什么可以讲的,但是这篇博客是详细讲解操作符,所以还是要讲解一下易错点吧!算术操作符,顾名思义就是数学上的一些运算:+、-、*、/、%。+、-、*这三个运算符没有什么可以讲的,接下来,小编重点讲解:/、%。
三、移位操作符(两个操作数)
小编在讲之前先提一嘴,移位操作符移动的是二进制的位。在这里,我们先来讲一下C语言的二进制。
3.1 左移操作符 <<
在常规的数字里面是不会出现特殊情况的,一般地,在效果上,左移一位相当于乘2。对于正数来说,还是对于负数来说,其实都一样,只是在一些特别大的数是不一样的,基本都遵循:丢弃符号位,不管左边高位是什么,后面补的数字成为符号位。
3.2 右移操作符 >>
小编先说一句:右移操作符比较难。首先右移运算分为两种:1.逻辑右移;2.算术右移。这两种主要的区别是:关键看左边补什么。
同样地,在常规的数字里面是不会出现特殊情况的,一般地,在效果上,右移一位相当于除以2。对于正数来说,遵循:丢弃右边一位,左边直接补0。而对于负数来说,有两种情况,所以一般请先了解你所使用的编译器是哪种右移运算,方法在下面。遵循:如果是算术右移:左边用原改制的符号位填充;如果是逻辑右移:左边补0。
对于正整数来说,这两种右移操作都一样;而对于负整数来说,这两种右移操作不太一样,所以要重点来看负整数。我们可以根据这个差异,编写一个代码看你们所使用的编译器支持哪种右移操作。vs用的是算术右移,大部分编译器用的都是算术右移。下面看代码:
#include <stdio.h>
int main()
{
int a = -10 >> 1;
if (a < 0)
printf("该编译器用的是算术右移!\n");
else
printf("该编译器用的是逻辑右移!\n");
return 0;
}
3.3 警告
四、位操作符(两个操作数)
在初学C语言时,老师应该是不会讲这一部分的,起码我们老师没有讲,但这一部分是非常重要的, 他在二进制的一些题目中有大作用。但大家不要将位操作符与逻辑操作符搞混!下面,就由小编我来带领大家进行分开学习吧!
4.1 按位与 &
我们记住这个运算规则后进行计算即可,下面进行代码讲解:
int main()
{
int a = 7;
int b = -10;
int c = a & b;//按二进制的位与
//00000000 00000000 00000000 00000111 ----- 7的补码
//10000000 00000000 00000000 00001010
//11111111 11111111 11111111 11110101
//*************************************
//*11111111 11111111 11111111 11110110*----- -10的补码
//*00000000 00000000 00000000 00000111*----- 7的补码
//*************************************
//同1为1,有0则0
//00000000 00000000 00000000 00000110 ----- 6
printf("%d", c);
return 0;
}
按位与的具体应用:
如果我想得到某个数的二进制补码上某一位到底是1还是0,我们可以使用按位与运算进行得到。为什么呢?
基本思路是:因为按位与的运算规则是:同1为1,有0则0。假如你想要求某个数的二进制补码上最后一位的数,你只需按位与上1(2^0),则可以得出某个数的二进制补码上最后一位的数是什么,如果按位与上1等于1的话,最后一个数是1,如果是0,则最后一个数是0。同理,如果你想要求某个数的二进制补码上倒数第二位的数,你只需按位与上2(2^1)。
4.2 按位或 |
这种运算是不需要进行讲解的,只要记住运算规则就会做运算,下面进行代码讲解:
int main()
{
int a = 7;
int b = -10;
int c = a | b;//按二进制的位或
//00000000 00000000 00000000 00000111 ----- 7的补码
//10000000 00000000 00000000 00001010
//11111111 11111111 11111111 11110101
//*************************************
//*11111111 11111111 11111111 11110110*----- -10的补码
//*00000000 00000000 00000000 00000111*----- 7的补码
//*************************************
//同0为0,有1则1
// 11111111 11111111 11111111 11110111 补码
// 11111111 11111111 11111111 11110110 反码
// 10000000 00000000 00000000 00001001 原码 --- -9
printf("%d", c);
return 0;
}
4.3 按位异或 ^
虽然,按位异或的运算规则比较简单,但是以后还要学习一个按位同或的运算规则:相同为1,不同为0。所以,这两种运算容易搞混。
那怎么记按位异或呢?按位异或——就是无进制相加。怎么理解无进制相加呢?看下图:
int main()
{
int a = 7;
int b = -10;
int c = a ^ b;//按二进制的位异或
//00000000 00000000 00000000 00000111 ----- 7的补码
//10000000 00000000 00000000 00001010
//11111111 11111111 11111111 11110101
//*************************************
//*11111111 11111111 11111111 11110110*----- -10的补码
//*00000000 00000000 00000000 00000111*----- 7的补码
//*************************************
//相同为0,不同为1
// 11111111 11111111 11111111 11110001 补码
// 11111111 11111111 11111111 11110000 反码
// 10000000 00000000 00000000 00001111 原码 --- -15
printf("%d", c);
return 0;
}
按位异或的具体应用:
一道很变态的面试题:
4.4 有关二进制位的练习
题目:编写代码实现:求一个整数存储在内存中的二进制中1的个数。
五、赋值操作符
赋值操作符是一个很棒的操作符,如果之前的值你不满意,使用这个操作符你可以给自己重新赋值。
复合赋值符
六、单目操作符(一个操作数)
6.1 单目操作符介绍
6.2 逻辑反操作符 !
下面看使用场景:
int main()
{
int a = 0;
if(!a)
printf("hehe\n");
return 0;
}
6.3 取地址操作符 & 和解引用操作符 *
取地址操作符是将一个变量的地址取出来存放在p中,解引用操作符是通过p所存放的地址找到p所指向的对象。
6.4 计算操作数的类型长度 sizeof
int main()
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof a); //这种写法是正确的,证明了sizeof不是函数,函数后的括号省略不了
printf("%d\n", sizeof(int));
return 0;
}
由上图代码可知,sizeof既能计算变量的长度,也能计算类型长度。此代码运行后,为什么会出现下图情况:
因为sizeof计算的结果是size_t类型的,size_t是无符号整形的,对size_t类型的数据进行打印,可以使用%zd。 在一些古老的编译器是不支持%zd的,也可以使用%u。
6.5 ++ 和 -- 操作符
七、关系操作符(两个操作符)
这些操作符比较简单,没有什么可以讲的,但是我们要注意一些运算符使用时候的陷阱。
八、逻辑操作符(两个操作符)
8.1 逻辑与操作符 &&
区分逻辑与和按位与
1 & 2 -------->0
1 && 2 -------->1
8.2 逻辑或操作符 ||
区分逻辑或和按位或
1 | 2 -------->3
1 || 2 ------->1
8.3 逻辑短路
学到这个操作符后,我突然想到了我同学问我的一道题目:
我刚看到这个题是有疑惑的,因为b和c选项感觉都是错的,其实并不是。因为c选项是涉及一些知识点是我不知道的,因为有逻辑短路,在C语言中,我们进行运算的时候,我们需要进行优化代码,不让这个程序进行超负荷的运算。在程序中,因为,a||(b = c)是这个逻辑运算,为什么会有逻辑短路呢?为了减少程序的计算量,在进行这个逻辑运算的时候,C语言采用了在保持原逻辑运算正确的同时,通过已确定表达式的确切值的情况下,不计算后面的运算来简化运算。
在或运算中,如果a为真,后面的值不管是什么,我们都不需要进行计算,因为程序的结果已经知道了,就应该进行逻辑短路,然后就不计算b = c,所以没有将c赋值给b, b还是等于原值。如果a为假,说明后面的结果可能会影响整个结果,所以就不能进行逻辑短路。
九、条件操作符(三目操作符)
我感觉这个操作符是用来简化代码的,具体看下面代码:
if (a > 5)
b = 3;
else
b = -3;
//等价于
b = a > 5 ? 3 : -3;
具体应用:
十、逗号表达式
下面看使用场景:
a = get_val();
couny_val(a);
while (a > 0)
{
//业务处理
a = get_val();
couny_val(a);
}
//如果使用逗号表达式,改写:
while (a = get_val(), couny_val(a), a > 0)
{
//业务处理
}
十一、下标引用、函数调用和结构成员
11.1 [ ]下标引用操作符(两个操作数)
int arr[10]; //创建数组
arr[9] = 10; //使用下标引用操作符
[ ]的两个操作数是arr和9。
11.2 ( )函数调用操作符(至少一个操作数)
11.3 访问一个结构的成员
总结
在这一部分,小编详细地编写了有关操作符详解的一篇博客。希望大家看完以后,进行点评,谢谢大家!