C语言入门篇(八)

╰+哭是因爲堅強的太久メ 2024-04-23 20:25 126阅读 0赞

前言
  本篇分享的是部分操作符的概念与用法,从经典例题入手,带你快速了解和掌握。
  收录专栏:浅谈C语言

操作符详解上

    1. 操作符分类
    1. 算术操作符
    1. 移位操作符
    • 3.1 左移操作符
    • 3.2 右移操作符
    1. 位操作符
    1. 赋值操作符
    1. 单目操作符
    • 6.1 单目操作符介绍
    • 6.2 sizeof 和 数组
    1. 关系操作符
    1. 逻辑操作符
    1. 条件操作符

1. 操作符分类

算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下标引用、函数调用和结构成员

2. 算术操作符

包括 + - * / %

例如:计算 3/2

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int a=3/2;
  5. printf("%d\n",a)
  6. return 0;
  7. }

如果你觉得这样写,就大错特错了。

? 运行结果:

在这里插入图片描述
这是因为这里的 a 是整型的,计算出的结果就是整型,会自动舍去小数点后的数字。

更改 a 的类型为浮点数:

  1. int main()
  2. {
  3. double a = 3 / 2;
  4. printf("%lf\n", a);
  5. return 0;
  6. }

其实,这样也是不对的。

? 运行结果:

在这里插入图片描述

仔细观察就会发现,这里的 a 虽然是 double 类型的,但 3 和 2 都是整形的, 3/2 计算后是 1,然后再将 1 装换成 double 型的赋给 a。

所以当计算的结果会出现浮点数时,除号的两端只要有一个小数就可以。

  1. int main()
  2. {
  3. //下面三种方式都可以计算出 1.5
  4. double a = 3.0 / 2.0;
  5. //double a = 3.0/2;
  6. //double a = 3 / 2.0;
  7. printf("%lf\n", a);
  8. return 0;
  9. }

注:
? 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数

? 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法

? 除法中,除数不可以为 0

? % 操作符的两个操作数必须为整数。返回的是整除之后的余数

3. 移位操作符

  1. << 左移操作符
  2. >> 右移操作符

移位操作符的操作数只能是整数。
移动的是二进制,因为能够处理的是二进制的信息

3.1 左移操作符

移位规则:左边抛弃、右边补0

例如:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int a = 15;
  5. printf("%d\n",a<<1);//移动就是a中的2进制信息
  6. return 0;
  7. }

? 图解:

在这里插入图片描述

? 运行结果:

在这里插入图片描述

3.2 右移操作符

移位规则:
首先右移运算分两种:

  • 逻辑移位
    左边用0填充,右边丢弃
  • 算术移位
    左边用原该值的符号位填充,右边丢弃

在C语言没有明确规定倒是算术右移还是逻辑右移,一般编译器上采用的是算术右移。

例如:

  1. int a = -1;

在这里插入图片描述

对于移位运算符,不要移动负数位,这个是标准未定义的。

例如:

  1. int a = 15;
  2. a>>-1;//error

移位移动的是补码的二进制序列

  1. //tip:
  2. int a = 15;
  3. //00000000000000000000000000001111 - 原码
  4. //00000000000000000000000000001111 - 反码
  5. //00000000000000000000000000001111 - 补码
  6. int b = -15;
  7. //10000000000000000000000000001111 - 原码
  8. //11111111111111111111111111110000 - 反码(原码的符号位不变,其他位按位取反得到的就是反码)
  9. //11111111111111111111111111110001 - 补码(反码+1就是补码)
  10. //整数在内存中存储的是补码
  11. //计算的时候也是使用补码计算的

4. 位操作符

位操作符有:(也是操作二进制位)

  1. & //按位与
  2. | //按位或
  3. ^ //按位异或

?上述的操作数必须是整数。

例如:

  1. // & 操作符
  2. #include<stdio.h>
  3. int main()
  4. {
  5. int a = 3;
  6. //00000000000000000000000000000011 - 补码
  7. int b = -5;
  8. //10000000000000000000000000000101
  9. //11111111111111111111111111111010
  10. //11111111111111111111111111111011 - 补码
  11. int c = a & b;
  12. //& -- 对应二进制位有0则为0,两个同时为1,才是1
  13. //00000000000000000000000000000011
  14. //11111111111111111111111111111011
  15. //00000000000000000000000000000011 - 补码
  16. printf("%d\n", c);//3
  17. return 0;
  18. }
  19. // | 操作符
  20. #include<stdio.h>
  21. int main()
  22. {
  23. int a = 3;
  24. //00000000000000000000000000000011 - 补码
  25. int b = -5;
  26. //10000000000000000000000000000101
  27. //11111111111111111111111111111010
  28. //11111111111111111111111111111011 - 补码
  29. int c = a | b;
  30. // | - 按(2进制)位或 - 对应的二进制位有1则为1,两个同时为0才是0
  31. //00000000000000000000000000000011
  32. //11111111111111111111111111111011
  33. //11111111111111111111111111111011 - 补码
  34. //11111111111111111111111111111010
  35. //10000000000000000000000000000101 - -5
  36. printf("%d\n", c);//-5
  37. return 0;
  38. }
  39. // ^ 操作符
  40. #include<stdio.h>
  41. int main()
  42. {
  43. int a = 3;
  44. //00000000000000000000000000000011 - 补码
  45. int b = -5;
  46. //10000000000000000000000000000101
  47. //11111111111111111111111111111010
  48. //11111111111111111111111111111011 - 补码
  49. //
  50. int c = a ^ b;
  51. //^ - 按二进制位异或 -对应的二进制位相同为0,相异为1
  52. //00000000000000000000000000000011
  53. //11111111111111111111111111111011
  54. //11111111111111111111111111111000 - 补码
  55. //11111111111111111111111111110111
  56. //10000000000000000000000000001000 - -8
  57. printf("%d\n", c);//-8
  58. return 0;
  59. }

实例1:交换2个整型变量

要想交换两个变量的值,最常见的方法是再创建一个变量,帮助我们实现:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int a = 3;
  5. int b = 5;
  6. //交换
  7. int tmp = a;//临时变量 tmp
  8. a = b;
  9. b = tmp;
  10. printf("交换前:a=%d b=%d\n", a, b);
  11. printf("交换后:a=%d b=%d\n", a, b);
  12. return 0;
  13. }

? 运行结果:

在这里插入图片描述

如果不创建临时变量(第三个变量),可以实现两个整数的交换吗?
回答是可以的

方法一:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int a = 3;
  5. int b = 5;
  6. a = a + b;
  7. b = a - b;
  8. a = a - b;
  9. printf("交换前:a=%d b=%d\n", a, b);
  10. printf("交换后:a=%d b=%d\n", a, b);
  11. return 0;
  12. }

? 运行结果:

在这里插入图片描述

方法二:使用 ^ 操作符实现

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int a = 3;
  5. int b = 5;
  6. printf("交换前:a=%d b=%d\n", a, b);
  7. a = a ^ b;
  8. b = a ^ b;
  9. a = a ^ b;
  10. printf("交换后:a=%d b=%d\n", a, b);
  11. return 0;
  12. }

? 运行结果:

在这里插入图片描述
异或操作符也支持交换律
例如:

  1. //a^a -> 0
  2. //a^0 = a
  3. #include<stdio.h>
  4. int main()
  5. {
  6. int a = 3;
  7. int b = 5;
  8. int c= a^b^a;
  9. int d= a^a^b;
  10. printf("%d %d\n", c, d);
  11. return 0;
  12. }

? 图解:
a ^b ^a=b
在这里插入图片描述

同样地,a^a^b=a

? 运行结果:

在这里插入图片描述

实例2:求一个整数存储在内存中的二进制中1的个数。

  1. //方法1
  2. #include <stdio.h>
  3. int main()
  4. {
  5. int num = 10;
  6. int count = 0;//计数
  7. while (num)
  8. {
  9. if (num % 2 == 1)
  10. count++;
  11. num = num / 2;
  12. }
  13. printf("二进制中1的个数 = %d\n", count);
  14. return 0;
  15. }
  16. //方法2:
  17. #include<stdio.h>
  18. int main()
  19. {
  20. int num = -1;
  21. int i = 0;
  22. int count = 0;//计数
  23. for (i = 0; i < 32; i++)
  24. {
  25. if (num & (1 << i))
  26. count++;
  27. }
  28. printf("二进制中1的个数 = %d\n", count);
  29. return 0;
  30. }
  31. //方法3,优化版本
  32. #include <stdio.h>
  33. int main()
  34. {
  35. int num = -1;
  36. int i = 0;
  37. int count = 0;//计数
  38. while (num)
  39. {
  40. count++;
  41. num = num & (num - 1);
  42. }
  43. printf("二进制中1的个数 = %d\n", count);
  44. return 0;
  45. }

5. 赋值操作符

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。

  1. int weight = 120;//体重
  2. weight = 89;//不满意就赋值
  3. double salary = 10000.0;
  4. salary = 20000.0;//使用赋值操作符赋值

赋值操作符可以连续使用
例如:

  1. int a = 10;
  2. int x = 0;
  3. int y = 20;
  4. a = x = y+1;//连续赋值

这样的代码感觉怎么样?
那同样的语义,你看看:

  1. x = y+1;
  2. a = x;

可见,下面的写法更加清晰爽朗而且易于调试。

复合赋值符

  1. +=
  2. -=
  3. *=
  4. /=
  5. %=
  6. >>=
  7. <<=
  8. &=
  9. |=
  10. ^=

这些运算符都可以写成复合的效果。
例如:

  1. int x = 10;
  2. x = x+10;
  3. x += 10;//复合赋值,与上面等式等价
  4. //但下面复合语句明显更加简洁。

其他运算符也是一样的道理。

6. 单目操作符

6.1 单目操作符介绍

  1. ! 逻辑反操作
  2. - 负值
  3. + 正值
  4. & 取地址
  5. sizeof 操作数的类型长度(以字节为单位)
  6. ~ 对一个数的二进制按位取反
  7. -- 前置、后置--
  8. ++ 前置、后置++
  9. * 间接访问操作符(解引用操作符)
  10. (类型) 强制类型转换

?单目操作符只有一个操作数

实例1:

  1. // ! 操作符
  2. //非 0 为真
  3. #include<stdio.h>
  4. int main()
  5. {
  6. int flag = 5;
  7. if (flag == 0)
  8. {
  9. printf("hehe\n");
  10. }
  11. if (!flag)//这里当 flag 为假时,才会打印hehe
  12. {
  13. printf("hehe\n");
  14. }
  15. if (flag)
  16. {
  17. printf("haha\n");
  18. }
  19. return 0;
  20. }

? 运行结果:

在这里插入图片描述

实例2: -

  1. // - 操作符
  2. #include<stdio.h>
  3. int main()
  4. {
  5. int a = 5;
  6. int b = -a;
  7. printf("%d\n", b);
  8. return 0;
  9. }

? 运行结果:

在这里插入图片描述

实例3: &

  1. // & * 操作符
  2. #include<stdio.h>
  3. int main()
  4. {
  5. int a = 10;
  6. //pa是指针变量
  7. int* pa = &a;//&-取地址操作符-取出a的地址
  8. *pa = 20;//解引用操作符(间接访问操作符)-单目操作符-通用pa中存放的地址,找到指向的空间(内容)
  9. //同时也更改了a 的内容
  10. int c = *pa;
  11. printf("a=%d c=%d\n",a, c);
  12. return 0;
  13. }

? 运行结果:

在这里插入图片描述

实例4:在计算数据类型所占内存大小时,可以使用 sizeof 操作数

? sizeof不是函数,是操作符
? sizeof计算的是类型创建变量的大小,单位是字节

  1. //sizeof 操作符:
  2. #include <stdio.h>
  3. int main()
  4. {
  5. int a = 10;
  6. printf("%d\n", sizeof(a));
  7. printf("%d\n", sizeof(int));
  8. printf("%d\n", sizeof a);
  9. //printf("%d\n", sizeof int);//不允许这样计算,说明 sizeof 不是函数
  10. return 0;
  11. }

实例5: ~

  1. // ~ 按补码二进制位取反
  2. #include<stdio.h>
  3. int main()
  4. {
  5. int a = 0;
  6. printf("%d\n", ~a);
  7. //00000000000000000000000000000000
  8. //11111111111111111111111111111111 - 补码
  9. //11111111111111111111111111111110
  10. //10000000000000000000000000000001 -1
  11. return 0;
  12. }

? 运行结果:

在这里插入图片描述

实例6:前置 ++ 、 后置 ++

  1. //前置++:先对变量进行自增,然后使用该变量
  2. int main()
  3. {
  4. int a = 1;
  5. int b = ++a;//前置++,先++,后使用
  6. //a=a+1,b=a
  7. printf("a=%d b=%d\n", a, b);//2 2
  8. return 0;
  9. }

? 运行结果:

在这里插入图片描述

  1. //后置++:先对a先使用,再自增
  2. #include<stdio.h>
  3. int main()
  4. {
  5. int a = 1;
  6. int b = a++;//后置++,先使用,后++
  7. //b=a,a=a+1
  8. printf("a=%d b=%d\n", a, b);//2 1
  9. return 0;
  10. }

? 运行结果:

在这里插入图片描述
前置--、后置--等同

6.2 sizeof 和 数组

实例:

  1. #include <stdio.h>
  2. void test1(int arr[])
  3. {
  4. printf("%d\n", sizeof(arr));//(2)
  5. }
  6. void test2(char ch[])
  7. {
  8. printf("%d\n", sizeof(ch));//(4)
  9. }
  10. int main()
  11. {
  12. int arr[10] = {
  13. 0 };
  14. char ch[10] = {
  15. 0 };
  16. printf("%d\n", sizeof(arr));//(1)
  17. printf("%d\n", sizeof(ch));//(3)
  18. test1(arr);
  19. test2(ch);
  20. return 0;
  21. }

? 运行结果:

在这里插入图片描述

7. 关系操作符

  1. >
  2. >=
  3. <
  4. <=
  5. != 用于测试“不相等”
  6. == 用于测试“相等”

?编写过程中 == 和 = 不要写错

实例:判断闰年

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int y = 0;
  5. scanf("%d", &y);
  6. //1. 能被4整除,并且不能被100整除
  7. //2. 能被400整除是闰年
  8. if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
  9. {
  10. printf("闰年\n");
  11. }
  12. else
  13. {
  14. printf("不是闰年\n");
  15. }
  16. return 0;
  17. }

8. 逻辑操作符

  1. && 逻辑与--并且
  2. || 逻辑或--或者
  3. 1&2----->0
  4. 1&&2---->1
  5. // & 两边二进制补码计算,相同为1,不同为0
  6. // && 两边同为真,结果也是真,用 1 表示;只要有一个为假,结果就是假,用 0 表示
  7. 1|2----->3
  8. 1||2---->1
  9. // | 两边二进制补码进行计算,只要有一个 1 就是 1;当两边都为 0 时,才是0
  10. // || 两边只有一个真时,就为真;都是假时,才为假

实例1:

  1. // &&
  2. #include <stdio.h>
  3. int main()
  4. {
  5. int i = 0, a = 0, b = 2, c = 3, d = 4;
  6. i = a++ && ++b && d++;
  7. printf("a = %d b = %d c = %d d = %d\n", a, b, c, d);
  8. return 0;
  9. }

? 运行结果:

在这里插入图片描述

实例2:

  1. // ||
  2. #include <stdio.h>
  3. int main()
  4. {
  5. int i = 0, a = 0, b = 2, c = 3, d = 4;
  6. i = a++||++b||d++;
  7. printf("a = %d b = %d c = %d d = %d\n", a, b, c, d);
  8. return 0;
  9. }

? 运行结果:

在这里插入图片描述

9. 条件操作符

  1. exp1 ? exp2 : exp3

实例:

  1. //如果 a>5,则 b=3
  2. //如果 a<=5,则 b=-3
  3. if (a > 5)
  4. b = 3;
  5. else
  6. b = -3;

上述代码可以转换成条件表达式:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a ;
  5. scanf("%d", &a);
  6. int b = a > 5 ? 3 : -3;
  7. printf("%d\n", b);
  8. return 0;
  9. }

? 运行结果:

在这里插入图片描述

使用条件表达式实现找两个数中较大值

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a, b ;
  5. scanf("%d %d", &a, &b);
  6. int c = a > b ? a : b;
  7. printf("%d\n", c);
  8. return 0;
  9. }

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,126人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C语言入门(五)

    现实生活中,库函数并不能解决所有问题,于是就有了自定义函数。自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计。statemen...

    相关 语言入门(四)

    > 前言 >   有的时候,我们可能需要多次执行同一块代码。 >   一般情况下,语句是按顺序执行的:函数中的第一个语句先执行,接着是第二个语句,依此类推。 >  

    相关 C语言入门(一)

    > 前言 >   欢迎各位小伙伴,这一篇,只是为了让我们对C语言有一个大概的认识,每个知识点并不会讲的很深,之后我也会持续更新博客,对这些知识进行拓宽,进行更细致的描述。