欢迎来到 Claffic 的博客 💞💞💞
前言:
我觉得学习语言,最直接的就是懂不懂符号,而符号中最突出的就是操作符,这期带大家认识认识C语言中的操作符及其使用。
目录
Part1:算数操作符
Part2:移位操作符
1.左移操作符
2.右移操作符
Part3:位操作符
Part4:赋值操作符
Part5:单目操作符
Part6:关系操作符
Part7:逻辑操作符
Part8:条件操作符
Part9:逗号表达式
Part10:下标,函数调用,结构成员
1.下标引用操作符[ ]
2.函数调用操作符( )
3.访问结构体成员
Part11:表达式求值
1.隐式类型转换
2.算数转换
3.操作符的属性
Part1:算数操作符
+ - * / %
其实就是常见的加减乘除,再加上一个取模(取余数);
不过它们的使用也遵照一些规则:
• 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。• 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。• % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
Part2:移位操作符
移位操作符包括这两个:
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数
1.左移操作符
位移规则:
左边抛弃,右边补0
实例:
注意:num本身的值不会变化,除非将左移后的结果赋值给num
2.右移操作符
位移规则:
右移运算分为两种类型:
• 逻辑移位左边用 0 填充,右边丢弃• 算术移位左边用原该值的符号位填充,右边丢弃
先说逻辑位移:
这个还是好理解的
算数位移:
符号位就是最左边的一位,原来的符号位是1,那么右移后补1即可,最后要还原回原码
Part3:位操作符
& //按位与:只有对应的两个二进位均为1时,结果位才为1,否则为0
| //按位或:只要对应的二个二进位有一个为1时,结果位就为1,否则为0
^ //按位异或:当两对应的二进位相异时,结果位为1,否则为0
注:位操作符的操作数只能是整数
举个例子:
按位与:
按位或:
按位异或:
对于异或操作符,有下列结论:
位操作符有什么用呢?
这里有一个常见好用的作用:
统计一个整数在存储中二进制的1的个数
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while(num)
{
count++;
num = num&(num-1);
}
printf("二进制中1的个数 = %d\n",count);
return 0;
}
Part4:赋值操作符
这种操作符就是方便:
当赋值的对象是本身时,起到修改自身的效果,此时就可以利用赋值操作符。
比如:
int x = 10;
x = x + 2; // 写法1
x += 2; // 写法2
是不是很简洁?
类似的,有符合赋值操作符:
+= x = x + n
-= x = x - n
*= x = x * n
/= x = x / n
%= x = x % n
>>= x = x >> n
<<= x = x << n
&= x = x & n
|= x = x | n
^= x = x ^ n
Part5:单目操作符
先看看单目操作符包括哪些吧:
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
! , - , + , sizeof 不再多说;
取地址&:
就是字面意思,得到某一个量的地址,在指针那块会经常用到;
二进制按位取反~:
这个意思好理解,就是按照补码,0对应位取反得1,1对应位取反得0,
不过并不常用... ...
前置、后置++/--:
先来解释++/--:
相当于 x += 1 / x -= 1;
在原数的基础上加/减1,原数改变。
那么这个前置和后置是什么意思?
看下面这几段代码:
#include<stdio.h>
int main()
{
int i = 10;
while (i--)
{
printf("%d ", i);
}
return 0;
}
输出: 9 8 7 6 5 4 3 2 1 0
#include<stdio.h>
int main()
{
int i = 10;
while (--i)
{
printf("%d ", i);
}
return 0;
}
输出:9 8 7 6 5 4 3 2 1
第二种相比第一种少了 0 ;
说明 前置--是先--,再使用,后置--是先使用,再--,++相同。
间接访问操作符(解引用操作符) *:
这个操作符就是由地址寻找所指量的操作符
Swap(int* a, int* b) // 传递的是地址
{
int tmp = *a; // 解引用操作,通过地址找到a;
*a = *b;
*b = tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(&a, &b);
printf("a = %d, b = %d", a, b);
return 0;
}
Part6:关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
这部分其实没啥好讲的,
注意判断相等 “==” 不要写成赋值 “=” 。
Part7:逻辑操作符
就两个:
&& 逻辑与
|| 逻辑或
它们与按位操作符是有些相近的:
& 这是按位与
| 这是按位或
两边放表达式还是好理解的,如果放数字呢?
像 1 && 2 ,1与2都是非0,都为真,逻辑与操作后是真,返回1;
1 || 0 ,1为真,0为假,逻辑或操作后是真,返回1;
Part8:条件操作符
exp1 ? exp2 : exp3
这个条件操作符其实就是三目操作符啦
它就相当于:
if (exp1)
exp2;
else
exp3;
Part9:逗号表达式
exp1, exp2, exp3, …expN
逗号表达式就是用逗号把表达式隔开;
从左向右执行;
整个表达式的结果是最后一个表达式的结果
可以看一个实例:
int main()
{
//代码1
int a = 1;
int b = 2; // a = 12 b = 13
int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
输出结果:12 13 13
Part10:下标,函数调用,结构成员
1.下标引用操作符[ ]
int arr[10];//创建10个元素的数组
arr[9] = 10;//使用下标引用操作符。
//[ ]的两个操作数是arr和9。
2.函数调用操作符( )
接受一个或者多个操作数:
第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h>
void test1()
{
printf("Hello world\n");
}
void test2(const char* str)
{
printf("%s\n", str);
}
int main()
{
test1(); // 使用()作为函数调用操作符。
test2("abcdef");
return 0;
}
3.访问结构体成员
. 结构体.成员名
-> 结构体指针->成员名
struct Stu
{
char name[10];
int age;
char sex[5];
};
int main()
{
struct Stu stu;
struct Stu* pStu = &stu;//结构成员访问
stu.age = 20;//结构成员访问
pStu->age = 20;//结构成员访问
return 0;
}
Part11:表达式求值
1.隐式类型转换
先说什么是整型提升:
C 的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为 整型提升。
再来看看整型提升是如何进行的:
整形提升是按照变量的数据类型的符号位来提升的。
//负数的整形提升
char c1 = -1; // 一个char类型1个字节大小,8个比特位
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//无符号整形提升,高位补0
2.算数转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换 。
// 排名看先后
long double
double
float
unsigned long int
long int
unsigned int
int
3.操作符的属性
说一个操作符有什么属性,也就是有什么影响的因素:
• 操作符的优先级• 操作符的结合性• 是否控制求值顺序
操作符优先级表:
// 表达式1
a*b + c*d + e*f;
代码 1 在计算的时候,由于 * 比 + 的优先级高,只能保证, * 的计算是比 + 早,但是优先级并不能决定第三个*比第一个+早执行。
//表达式2
c + --c;
同上,操作符的优先级只能决定自减--的运算在+的运算的前面,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义
的。
//代码3-非法表达式
int main()
{
int i = 10;
i = i-- - --i * ( i = -3 ) * i++ + ++i;
printf("i = %d\n", i);
return 0;
}
这个结果取决于编译器,这里就不展示结果,因为没有参考价值。
总结:
这篇博客进行了操作符的讲解,不要问操作符为什么长这样,能理解的理解并尝试取用一下,不能理解的先好好记住,刚开始有操作符不会用是很正常的,建议多走读代码,进而自己能敲出自己的代码~
码文不易
如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦 💗💗💗