前言
本次博客一定会让刚刚学习C语言小白有所收获
本次操作符讲解不仅分类还会有代码示例
好好看 好好学 花上几分钟就可以避免许多坑
1 操作符的基本使用
1.1操作符的分类
按功能分
算术操作符: + 、- 、* 、/ 、%
移位操作符: >> <<
位操作符: & | ^
赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、>>= 、&= 、|= 、^=
单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof(类型)
关系操作符: > 、>= 、< 、<= 、 == 、 !=
逻辑操作符: && 、||
(三目操作符)条件操作符: ? :
逗号表达式: ,
下标引⽤: []
函数调⽤: ()
按性质分为 单目操作符 双目操作符 三目操作符
主要的区分是 单目为一个操作数 双目为两个操作数 三目操作符为三个操作数
1.2操作符的使用
1.21算术操作符
对于算术操作符来说,值得注意的点只有 / %
对于加减乘 任何数据都能实现,但是 除法
在遇到整数时,首先除数不能为0,其次除不尽是只会保留整数
比如 2 /1=2 1/2=0 5/3=1
当然如果是浮点数会保留的 1/2.0=0.5
如果是%(求模) 注意它只服务于整型数据取得的数为余数
大家看看代码呗
是不是 % 只能对整数有效
让大家看看结果
10/3只能保留3 10%3余下一个1
这里没有讲解 加减乘 大家可以自行操作,就是数学中的普通四则运算
1.22移位操作符
>> <<
移位操作符的操作数只能是整数
<< 左移操作符
移位规则:左边抛弃、右边补0
我们举两个例子来说明情况
注意整型在内存中的存储为补码,我们分别以 -1 与+1来进行左移操作
这是对一的左移
先画图
画的一般,但是能看
继续看-1的左移
我们看看代码
此时a 和 b的大小都变为2倍
>>右移操作符
位规则:⾸先右移运算分两种:
1. 逻辑右移:左边⽤0填充,右边丢弃
2. 算术右移:左边⽤原该值的符号位填充,右边丢弃
我们的编译器一般都是算术右移
直接看代码
#inlcude<stdio.h>
int main()
{
int a = 2;
int b = -2;
printf("%d", a >> 1);
printf(" %d", b >> 1);
return 0;
}
看结果
所以左移操作符的作用是 在不溢出的情况下,使原有的数*2
右移操作符的作用是 在不溢出的情况下,使原有的数/2
1.23位操作符
& 按位与 | 按位或 ^ 按位异或 ~按位取反
位操作 这里只讲简单的原理即可
1& 按位与
画图吧
2 | 按位或
看图
3^ 按位异或
看图
4按位取反
看图
注意一下再char类型中是如此 它的范围为 -128~127
而short类型的 它的范围为-32768~32767
我们可以看看 它的-32768的原码为
1000 0000 0000 0000
值得注意的是它的补码也是 1000 0000 0000
ok 上述代码都可以通过代码实现
是不是对应上了
1.24赋值操作符:
= 、+= 、 -= 、 *= 、 /= 、%= 、>>= 、&= 、|= 、^=
其实这个没什么可讲的,就是赋值
看代码
int main()
{
char a = 1;
char b = 126;
a = 28;//把28赋值给a
a += 10;//a=a+10
a -= 10;//a=a-10;
a *= 10;//a=a*10;
a /= 10;//a=a/10;
a %= 10;//a=a%10;
a >>= 10;//a=a>>10;
a &= 1;//a=a&1;
return 0;
}
1.25单⽬操作符
++ -- ! & sizeof()
前置++ --
是先++ --后使用
后置 ++ --
是先使用后++ --
!是使非0的值变为0 使0变为1
简单举例子就好
int main()
{
int a = 0;
int b = 1;
int c = 1;
if (++a)
printf("++a是先加1在使用进入判断哦\n");
if (!--b)
printf("--b是先减去1在进入判断哦\n");
if (c--)
printf("c--是先使用才会减1哦\n");
return 0;
}
看结果
& sizeof()
&作为单目操作符为去某个数据的地址与 双目操作符&按位与是不同的含义
sizeof()是计算某个数据所占的内存大小
看代码
int main()
{
int a = 10;
int* p = &a;
*p = 20;//改变a的值
int b = sizeof(p);//计算指针类型的大小
int c = sizeof(b);//计算int类型的大小
printf("%d %d %d ", a, b, c);
return 0;
}
1.26关系操作符:
> 、>= 、< 、<= 、 == 、 !=
这其实更没有必要讲解l
其实就是数学里的比大小,如果成立返回1,不成立返回0
!=为不等于
看代码
所以懂了吗
1.27逻辑操作符
&& 、||
逻辑操作符也是一个很重要的操作符
&&逻辑与 (表达式1)&&(表达式2) 只有两个都为真时 整个式子才为真
||逻辑或 (表达式1)||(表达式2)只要一个为真时 整个式子就为真
给一个最简单的代码吧
int main()
{
int a = 0 && 0;
int b = 1 && 1;
int c = 1 && 0;
int a1 = 0 || 0;
int b1 = 1 || 1;
int c1 = 1 || 0;
printf("%d %d %d",a,b,c);
printf("%d %d %d", a1, b1, c1);
return 0;
}
看结果
当然有注意点的
1两端其实可以是表达式的
2对于(表达式1)&&(表达式2)只要 表达式1为假 那么表达式二直接不运算,整个式子的值为0
3对于(表达式1)||(表达式2)只要 表达式1为真 那么表达式而同样不计算 ,整个式子的值就为1
1.28(三目操作符)条件操作符
(表达式1)? (表达式2):(表达式3)
如果表达式1为真则执行表达式1否者执行表达式2
很简单
看代码
int main()
{
int a = 10;
int b = 20;
//三目操作符
int c = 10 > 20 ? 10 - 20 : 10 + 20;
int d = a>10?10:20;
//注意后面的表达式只能是一个确切的值,不能是一个赋值表达式
//a > b ? a + 20 : b =30;//error
printf("%d %d %d %d", a, b, c, d);
//还有一种用途,可以用在打印里头 条件打印
printf(a > b ? "*" : "1");
return 0;
}
1.29逗号表达式:
是从左到右依次执行代码,取最后一个表达式的值为返回值 看语法
(表达式1,表达式2,表达式3,表达式4,表达式5,表达式6······,表达式n)
, 只是一个小小的逗号可能还看不出什么,我们还是看代码说话
int main()
{
int a = 10;
int b = 20;
int c = 30;
int d = (a = 30, b++, c += 60, 20);
//那么此时 a为30 b为21 c为90 d取上最后一个表达式的值为20
//看结果
printf("%d %d %d %d", a, b, c, d);
return 0;
}
1.30下标引用 函数调⽤
[] ()
下标引用 主要用于数组中调用任意位置中的元素
当然他也可以对指针使用等效于 a[0]==*(a+0)
函数调用符号更没什么好讲了,用于函数的调用以及定义
还是举例看代码就好
void haha(int a,int b);//这是函数声明,用了 ()
int main()
{
int a=20;
int *p=&a;
int c=p[0];//算是解引用的一种
int arr[20]={0};//对数组的定义
return 0;
}
至此几乎所有的操作符的基本使用都讲解完了接下来看看优先级以及结合性
1.3操作符的属性
分为优先级、结合性
先上一张图
1.31优先级结合性
优先级 优先级指的是,如果⼀个表达式包含多个运算符,哪个运算符应该优先执⾏。各种运算符的优先级是 不⼀样的
比如
3 + 4 * 5;
上⾯示例中,表达式 3 + 4 * 5 ⾥⾯既有加法运算符( + ),⼜有乘法运算符( * )。由于乘法 的优先级高于加法,所以会先计算 4 * 5 ,⽽不是先计算 3 + 4
结合性
如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符 是左结合,还是右结合,决定执⾏顺序。⼤部分运算符是左结合(从左到右执⾏),少数运算符是右 结合(从右到左执⾏),⽐如赋值运算符( = )
5 * 6 / 2;
上⾯⽰例中, * 和 / 的优先级相同,它们都是左结合运算符,所以从左到右执⾏,先计算 5 * 6 , 再计算 6 / 2
运算符的优先级顺序很多,下⾯是部分运算符的优先级顺序(按照优先级从⾼到低排列),建议⼤概 记住这些操作符的优先级就⾏,其他操作符在使⽤的时候查看下⾯表格就可以了
我们可以列出几个优先级问题的代码,一般而言优先级不需要特殊记忆,只要多敲多练即可
看看代码
int main()
{
int a = 10;
//看看,如果我们要让a先左移两位再按位与上一个1,就必须要加上括号
//否则此时是先2与1逻辑与再左移
int d =(a<<2)&1;
return 0;
}
//这个很容易搞错,大家以后会遇到这样的代码
再看一个例子
int main()
{
int arr[20] = {0};
int** parr = &arr;
//不加上括号的话编译器无法知道 是先执行 * 还是[] 所以要加上()
(*parr)[10] = 1;
return 0;
}
这类例子还有很多,基本上都是解引用的优先级一样不知道先使用那个解应用
对于结合性只需记忆一个点
1 赋值操作符都是从右往左
2三目操作符从右往左
3其他基本都是从左往右
总结
大家还是要多练,才能有理解,祝大家开心