当前位置:网站首页>【c】操作符详解(二)
【c】操作符详解(二)
2022-08-04 09:22:00 【silence-Tan】
哈喽大家好,大家好,欢迎收看本期博客 !
我是Mr.tan
今天呢,给大家分享剩下的c语言中的操作符,希望对大家学习c语言能有所帮助。
一、赋值操作符
操作符: | 描述: | 用法案例: | 结合性: |
= | 赋值 | a = 2 | R-L |
+= | 以……加 | a += 2 | R-L |
-= | 以……减 | a -= 2 | R-L |
*= | 以……乘 | a *= 2 | R-L |
/= | 以……除 | a /= 2 | R-L |
%= | 以……整数取余 | a %= 2 | R-L |
>>= | 以……右移 | a >>= 2 | R-L |
<<= | 以……左移 | a <<= 2 | R-L |
&= | 以……与 | a &= 2 | R-L |
|= | 以……或 | a |= 2 | R-L |
^= | 以……异或 | a ^= 2 | R-L |
1、赋值
对于赋值操作符,我们经常能用到,当我们对我们的身高和颜值不满意时,我们可以用赋值操作符来制定我们的目标。比如:
int tall = 175;//目前身高
tall = 185;//目标身高
int face_score = 70;//目前颜值分数
face_score = 90;//目标颜值分数
2、连续赋值
当我们知道连续赋值的工作原理时,我们很容易理解,但是对于连续赋值也是有缺陷的,它不方便调试,当我们想观察每一步的细节时,它是观察不到位的。
int a = 10;
int b = 0;
b = a = a + 3;
所以未来大家在写代码的过程中,是不建议这种写法的,同样的语句我们可以分开写,这样不仅方便我们的调试,观察时也清晰。
int a = 10;
int b = 0;
a = a + 3;
b = a;
3、复合赋值
在看复合赋值之前,我们先观察下面两段代码:
//代码1
int main()
{
int a = 8;
a = a + 1;
printf("a=%d\n",a);
int b = 8;
b = b >> 2;
printf("b=%d\n", b);
int c = 8;
c = c * 3;
printf("c=%d\n", c);
int d = 8;
d = d | 1;
printf("d=%d\n", d);
return 0;
}
//代码2
int main()
{
int a = 8;
a += 1;
printf("a=%d\n",a);
int b = 8;
b >>= 2;
printf("b=%d\n", b);
int c = 8;
c *= 3;
printf("c=%d\n", c);
int d = 8;
d |= 1;
printf("d=%d\n", d);
return 0;
}
但我们仔细对比两个程序,我们会发现当我们对变量自身操作后,再将值赋给自己时,我们可以将常规写法改写成复合赋值的形式,这样就充分的运用了我们所学的知识。复合赋值中的其它操作符也能写成这样,在此我们就不一一列举了。
二、单目运算符
操作符: | 描述: | 用法案例: | 结合性: |
! | 逻辑反 | !a | R-L |
+ | 正号 | +3 | R-L |
- | 负号 | -2 | R-L |
& | 取地址 | &a | R-L |
* | 解引用 | *pa | R-L |
sizeof | 操作数类型长度 | sizeof(int) | R-L |
~ | 按位取反 | ~2 | R-L |
++ | 前、后缀自增 | ++2、2++ | (前缀)R-L(后缀)L-R |
-- | 前、后缀自减 | --1、1-- | (前缀)R-L(后缀)L-R |
() | 强制类型转换 | (int) 3.6 | R-L |
1、逻辑反操作
对于这个运算符,它的作用就是把真变成假,把假变成真(如图所示)。当我们看见第一段程序时,我们会发现if语句中的条件为假,将不运行printf语句。
//代码段1
int main()
{
int flag = 0;
if (flag)
{
printf("谭谭粉丝最帅!\n");
}
return 0;
}
//代码段2
int main()
{
int flag = 1;
if (!flag)
{
printf("谭谭粉丝最帅!\n");
}
return 0;
}
但是我们将if语句中的条件之前加上逻辑反操作的运算符,它将执行printf语句,并打印出“谭谭粉丝最帅!”(如图所示)。
int main()
{
int flag = 0;
if (!flag)
{
printf("谭谭粉丝最帅!\n");
}
return 0;
}
2、正负号
对于正负号,我想大家应该是非常了解了吧!在变量的初始化时,我们可以给int、float、double等类型的值赋一个正数(正号省略不写),也可以赋一个负数(在变量之前加一个减号);
int main()
{
int a = -3 ;
int b = 4;
printf("a=%d b=%d\n",a,b);
return 0;
}
3、取地址符与解引用符
取地址符
创建变量的本质,一定是在内存中开辟一段存储空间。而内存中的每一个单元都有自己的编号,假设创建一个int类型的变量,那么整形变量中的4个字节都有自己的地址,如果我们想观察首个字节的地址,我们只需要在变量之前加一个&,而打印出来的结果是一个十六进制的数字。
int main()
{
int a = 10 ;
char b = 0;
printf("%p\n",&a);
printf("%p\n",&b);
return 0;
}
解引用
当我们想把这个数值存起来的时候,我们可以把它放进pa里面去,那么我们就可以把pa认为是一个指针变量,pa是专门用来存放a的地址。对于int* pa = 0这一语句中的*是告诉我们pa是指针变量,而它前面的int*是告诉我们pa所指的a的类型,而pa为变量名。pa里面存的是a的地址,当有一天我们想通过pa找到我们的a,只需要在pa的前面加上解引用操作符,如果单纯的只想得到a的地址,只需要pa即可。
int main()
{
int a = 10 ;
char b = 0;
int* pa = &a;
*pa = 20;
printf("%d\n", a);
printf("%p\n", pa);
return 0;
}
4、sizeof
sizeof是求操作数的类型长度的,而%zu是专门打印sizeof的返回值的。
int main()
{
int a = 10 ;
int* pa;
int arr[10];
printf("%zu\n",sizeof(a));
printf("%zu\n", sizeof(pa));
//sizeof(数组名),数组名表示整个数组,不是首元素的地址,它是求整个数组的大小,单位为字节
printf("%zu\n", sizeof(arr));
return 0;
}
int main()
{
short m = 5;
int a = 2;
printf("%zu\n", sizeof(m = a + 5));//sizeof内部放的表达式不计算
printf("%d\n", m);
return 0;
}
对于代码段中的语句,a为int类型的变量,在内存中占用四个字节,m为short类型的变量,在内存中占两个字节。把a加5之后放到m中去会发生截断,因为把int类型的变量占用的内存空间比short类型大,它放不下,所以表达式最终会取决于short类型,而sizeof是求操作数的类型长度的,所以最后打印出来的结果前者为2。sizeof内部放的表达式不计算,所以打印出来的m为5
而对于sizeof的写法有三种形式:
//三种正确写法
printf("%zu\n",sizeof(a));
printf("%zu\n", sizeof a);
printf("%zu\n", sizeof(int));
//错误写法
printf("%zu\n",sizeof int);
注意:如果sizeof后面为变量的类型,那么小括号是不能省略的,这是一种错误的写法,编译器会报错。
5、自增自减运算符
前置++与前置--
int main()
{
int a = 10;
int x = 0;
int y = 0;
x = ++a;
printf("%d\n", a);
//先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。
y = --a;
printf("%d\n", a);
//先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10;
printf("%d %d", x, y);
return 0;
}
后置++与后置--
int main()
{
int a = 10;
int x = 0;
int y = 0;
x = a++;
printf("%d\n", x);
printf("%d\n", a);
//先对a先使用,再增加,这样x的值是10;之后a变成11;
y = a--;
printf("%d\n", y);
printf("%d\n", a);
//先对a先使用,再自减,这样y的值是11;之后a变成10;
return 0;
}
让我们通过一个例题来彻底学会自增自减的运算关系,当我们观察完代码之后请看下方的表格,表格中的各结果标明的非常清楚。
int main()
{
int a=2;
int b=2;
int c=2;
int d=2;
a++;
b--;
++c;
--d;
return 0;
}
表达式: | 表达式执行前变量值: | 表达式执行后变量值: | 表达式的值: |
a++ | 2 | 3 | 2 |
b-- | 2 | 1 | 2 |
++c | 2 | 3 | 3 |
--d | 2 | 1 | 1 |
6、按位取反
int main()
{
int a = 3;
//00000000 00000000 00000000 00000011 按位取反前的补码
//11111111 11111111 11111111 11111100 按位取反后的补码
//11111111 11111111 11111111 11111011 按位取反后的反码
//10000000 00000000 00000000 00000100 按位取反后的原码
printf("%d\n", ~a);
return 0;
}
~是对一个数的二进制按位取反 .将a按位取反后的原码转换为十进制数为-4,与我们打印出来的结果完全契合。
7、强制类型转换
(1)、将实数转换为整数时,系统采用的是截断方式,而不是4舍5入。
int main()
{
int a;
a = (int)3.8;
printf("%d\n", a);
return 0;
}
(2)、对变量进行强制类型转换后,变量的数据类型不变,而是得到一个所需类型的数据。
int main()
{
double x = 3.6;
int i;
i = (int)x;
//i为3,x为3.6,x为double型,i为整型。
printf("%d\n", i);
printf("%zu\n", sizeof(x));
printf("%zu\n", sizeof(i));
return 0;
}
三、关系操作符
操作符: | 描述: | 用法案例: | 结合性: |
== | 等于 | 2 == 2 | L-R |
> | 大于 | a > b | L-R |
>= | 大于等于 | a >= c | L-R |
< | 小于 | b < d | L-R |
<= | 小于等于 | b <= f | L-R |
!= | 不等于 | a != f | L-R |
对于关系运算符,我想大家不管是在数学中还是在c语言中都已经再熟悉不过了,在这里要注意的有:
1、两个=为判断是否相等,而一个=为赋值,在写代码的过程中千万不要把它们搞混;
2、==不能比较两个字符串的内容,实际上比较的是两个字符串的首字符的地址;
3、关系运算符的优先级低于算术运算符,高于赋值运算符;
4、我们将判断的结果进行打印后, 1 为“真”,表示条件成立,而 0 为“假”,表示条件不成立。
四、逻辑运算符
运算符: | 描述: | 用法案例: | 结合性: |
&& | 逻辑与 | a && b | L-R |
|| | 逻辑或 | c || d | L-R |
1、逻辑与
//代码1
int main()
{
int a = 2;
int b = 4;
if (a && b)
{
printf("小比特,大梦想!");
}
return 0;
}
//代码2
int main()
{
int a = 2;
int b = 0;
if (a && b)
{
printf("小比特,大梦想!");
}
return 0;
}
逻辑或的两边同时为真,整个式子才为真,只要有一个为假,整个式子就为假。对于代码段中的表达式a&&b,先看a的值等不等于0,如果a等于0就不再计算b;如果a不等于0再去计算b;
2、逻辑或
//代码1
int main()
{
int a = 0;
int b = 4 - 4;
if (a || b)
{
printf("小比特,大梦想!");
}
return 0;
}
//代码2
int main()
{
int a = 2 + 3;
int b = 4 - 4;
if (a || b)
{
printf("小比特,大梦想!");
}
return 0;
}
对于逻辑或的运算,先判断逻辑或左边的表达式,当左边的表达式不等于0的时候就不要再计算右边的表达式,如果左边的表达式等于0的时候再计算右边的表达式即可。而逻辑或的两边只要有一个为真,整个式子就为真,如果两边都为假,则整个式子为假。
逻辑与的优先级别高于逻辑或,而他们两个都低于关系运算符,并且都高于赋值运算!
五、条件操作符
操作符: | 描述: | 用法案例: | 结合性: |
? : | 条件操作符 | a > b ? 2 : 3 | L-R |
int main()
{
int a = 3;
int b = 2;
int c;
c = ((a > b) ? 4 : -1);
printf("%d\n", c);
return 0;
}
如果a>b则c的值为4,否则c的值为-1;这段代码充分的展现了条件操作符的作用!
六、逗号表达式
操作符: | 描述: | 用法案例: | 结合性: |
, | 逗号 | a=2+3,b=a-1,c=b*2 | L-R |
int main()
{
int a = 1;
int b = 2;
int c = (a =a + 2, b = b + 3, a = a + b,b = a + 1);
printf("%d\n", c);
return 0;
}
欢迎大家的收看本期内容,今天的内容到此结束了,对于c语言操作符的详解到这里就跟大家告别一段落了,让我们期待下一篇的文章到来吧!
如果喜欢,那就一键三连吧!!!
边栏推荐
- LeetCode中等题之设计循环队列
- cannot import name 'import_string' from 'werkzeug' [bug solution]
- MATLAB绘图总结
- leetcode动态规划经典例题——53.最大子数组和
- Fiddler(二)-手机抓包502错误解决方法
- The separation configuration Libpq is supported, speaking, reading and writing
- No module named 'flask_misaka' has been resolved [BUG solution]
- 菲沃泰科创板上市:市值123亿 宗坚赵静艳夫妇身价76亿
- [Punctuality Atom STM32 Serial] Chapter 2 STM32 Introduction Excerpted from [Punctual Atom] MiniPro STM32H750 Development Guide_V1.1
- 我和 TiDB 的故事 | TiDB 对我不离不弃,我亦如此
猜你喜欢
随机推荐
leetcode每天5题-Day06
MindSpore:mirrorpad算子速度过慢的问题
How to restore the Youxuan database with only data files
cannot import name ‘import_string‘ from ‘werkzeug‘【bug解决】
leetcode经典例题——49.字母异位词分组
他97年的,我既然卷不过他...
Post-94 Byte P7 posted the salary slip: It's really good to make up for this...
关于技术学习的6个观点
关于DSP驱动外挂flash
学习使用php把stdClass Object转array的方法整理
请问同一个oracle cdc表,如果flink job重新提交,是会全量读取一遍源数据还是增量呢?
2022年化工自动化控制仪表考试模拟100题及模拟考试
TiCDC迁移-TiDB到MySQL测试
暴力破解-破解 Apache BASIC 认证
各位大佬,请问mysql数据的cdc,能指定存量数据同步的zone为utc 吗
思想茶叶蛋 (Jul 31,2022)| 元宇宙(Metaverse)下了一枚什么样的蛋
请问下Flink SQL如何写hologres分区表?我想要每天一个分区
Oracle怎么获取当前库或者同一台服务器上某几个库的数据总行数?
密码字典生成工具pydictor/john
学习在php中分析switch与ifelse的执行效率