目录
第一部分、常见操作符
第二部分、每个操作符的具体使用
1、算术操作符
1.1、除法运算符 /
1.2、取模运算符 %
2、移位操作符
2.1、左移 <<
2.2、右移 >>
3、位操作符
3.1、按位异或的妙用
3.2、按位与的妙用
4、单目操作符
4.1、逻辑反操作符 !
4.2、sizeof操作符
4.3、按位取反~
4.4、强制类型转换
5、三目操作符(条件操作符)
6、逗号表达式
第三部分、往期文章
第一部分、常见操作符
操作符类型 | 相应的操作符 |
算术操作符 | 加+ 减- 乘* 除/ 取模% |
移位操作符 | 左移<< 右移>> |
位操作符 | 按位与& 按位或| 按位异或^ |
复合赋值操作符 | 加等于+= 减等于-= 乘等于*= 模等于/= 余等于%= 按位与&= 按位异或等于^= 按位或等于|= 右移等于>>= 左移等于<<= |
单目操作符(只有一个操作数) | 逻辑取反操作! 取地址& 计算操作数的类型长度sizeof 按位取反~ 前置、后置++ 前置、后置-- 解引用操作符(间接访问)* 强制类型转换(类型)X 地(X为变量或者指针) |
关系操作符 | 大于> 大于等于>= 小于< 小于等于<= 等于等于== 不等于!= |
逻辑操作符 | 逻辑与&& 逻辑或|| |
条件操作符(三目操作符) | exp1 ? exp2 : exp3 |
逗号表达式 | 从左往右执行exp1,exp2,exp3,exp4 |
下标引用、函数调用和结构成员 | 下标引用[] 函数调用() 访问结构成员. 指针访问结构体成员-> |
第二部分、每个操作符的具体使用
这里主要记录一些使用这些操作符的基本知识,有些太简单,我就不没有记录。
1、算术操作符
1.1、除法运算符 /
如果除号两边都是整数执行的是整数除法,如果被除数与除数之间有一个是小数,那么计算结果就是小数。示例如下:
1.2、取模运算符 %
% 操作符的两个操作数必须为整数。返回的是整除之后的余数。
2、移位操作符
注意:移位操作符的操作数只能是整数。
2.1、左移 <<
向左移位,右边永远补0。(小技巧:对于偶数,左移1位等价于除以2,因此在FPGA内部便可用左移的方式代替除法,减少逻辑资源的使用。)
2.2、右移 >>
当操作数为正数时:向右移位,左边补0。
当操作时为负数时:分为两种情况:(取决于编译器)
方式一、逻辑移位:左边用0填充,右边丢弃(包括符号位)
方式二、算术移位:左边用该值的符号位填充,右边丢弃(一般情况下是算数右移)
验证编译器的移位方式,示例如下:
因为a = -1,其在内存中的存储方式为:11111111_11111111_11111111_11111111,根据算术移位,其值不发生改变。
如果该编译器的右移方式为逻辑移位时:01111111_11111111_11111111_11111111,该值为一个很大的正数。
3、位操作符
合理的使用位操作符,得到的代码可太妙了。其次注意:位操作符的操作数也为整数。
3.1、按位异或的妙用
示例、不定义中间变量的方式,实现两个整数 a,b值之间的互换。
int a = 3,b =5;
//按位异或的方式
a = a ^ b;
b = a ^ b;//b = a^b^b
a = a ^ b;//a = a^b^a
//相加的方式,容易溢出
a = a + b;//8(缺点,a,b值太大时容易溢出)
b = a - b;//8 - 5 = 3
a = a - b;//8 - 3 = 5
3.2、按位与的妙用
示例、求一个整数存储在内存中的二进制中1的个数。
方法1、常规思路
int main()
{
int a = -1;
int count = 0;
for (int i = 0;i < 32; i++)
{
if (a & (1<<i))//注意这里的写法,不用去定义一个变量让他去移位
{
count++;
}
}
printf("%d\n", count);
return 0;
}
方法2、大佬思路
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while (num)
{
count++;
num = num & (num - 1);//num 与 num - 1 相与
}
printf("二进制中1的个数 = %d\n", count);
return 0;
}
4、单目操作符
4.1、逻辑反操作符 !
注意:C语言中,0就是假,非0就为真。 a = 100 ;!a = 0;
4.2、sizeof操作符
sizeof的作用:以字节为单位给出与变量或类型在内存中所占的空间大小。
注意:1. sizeof计算字符串的时候会算入\0。
2. sizeof括号内部的表达式是不参与运算的!结果只有a的类型决定,定义a的时候已经给a开辟了空间。
如下图:
关于sizeof的用法还是很多的,例如下面两张截图展示的内容。
例如1、计算不同类型变量所占空间大小
例如2、用来计算整型数组的长度(会常用!!!)
数组长度再进行传参的时候,只能在外部提前计算好数组的长度,随后再进行传参。
4.3、按位取反~
对某个数取反,是将其在内存中的二进制数据(补码)进行按位取反。
这里为啥是-1?应该懂了吧。
4.4、强制类型转换
变量前面右括号,括号里面还有类型,那么就是强制类型转换。
(数据类型)变量
- 强制类型的正常用法
- 强制类型的更妙的用法(涉及到后面的指针的一些知识)
void* :示任何类表型的地址都可以放进去。无论是char*,int*还是其他指针类型,都可以用void*来存放。
用通俗的话来说,void* 就是指针类型变量的垃圾桶,可以存放任何类型变量的地址。
因此,利用这一点,就有了一个应用场景,在编写函数的入口参数时,我不知道传入该函数的参数是什么指针类型,那么此时我先用void*来存放该指针,等我函数里面要用到该指针的时候我再去进行强制类型转换。妙的压批!
5、三目操作符(条件操作符)
说实话,我个人认为该操作符在C语言里面经常被人遗忘,也可能是我接触的C太少。但是这个操作符在verilog HDL里面可是一个宠儿,大宠儿。
在verilog里面和assign赋值语句一起用,能够解决输出结果存在一个周期延迟的问题。这里不探讨太多,后面关于verilog 中如何使用,我会详细解释。
exp1 ?exp2 :exp3;
exp1成立,整个表达式返回exp2的值,如果exp1不成立,整个表达式返回exp3的值。
6、逗号表达式
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
示例如下:用来简化代码。
int main()
{
a = get_val();
count_val(a);
while (a > 0)
{
a = get_val();
count_val(a);
}
return 0;
}
//等价于
int main()
{
while (a = get_val(), count_val(a),a > 0)
{
}
return 0;
}
第三部分、往期文章
希望我的笔记对你有帮助,有需要的小伙伴可以看一下往期的文章🤪🤪🤪
【C语言复习】第一篇、关于我的C语言的复习路线_大屁桃的博客-CSDN博客
【C语言复习】第二篇、VS2017软件的使用以及常用小技巧_大屁桃的博客-CSDN博客
【C语言复习】第三篇、Gitee码云的创建和使用_大屁桃的博客-CSDN博客
【C语言复习】第四篇、有关C语言数据类型的知识_大屁桃的博客-CSDN博客
【C语言复习】第五篇、变量,常量,字符串,转义字符的知识_大屁桃的博客-CSDN博客