C语言入门篇(八)

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

操作符详解上

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

1. 操作符分类

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

2. 算术操作符

包括 + - * / %

例如:计算 3/2

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

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

🍤 运行结果:

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

更改 a 的类型为浮点数:

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

其实,这样也是不对的。

🍤 运行结果:

在这里插入图片描述

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

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

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

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

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

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

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

3. 移位操作符

 << 左移操作符>> 右移操作符

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

3.1 左移操作符

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

例如:

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

🍤 图解:

在这里插入图片描述

🍤 运行结果:

在这里插入图片描述

3.2 右移操作符

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

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

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

例如:

int a = -1;	

在这里插入图片描述

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

例如:

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

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

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

4. 位操作符

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

& //按位与
| //按位或
^ //按位异或

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

例如:

// & 操作符
#include<stdio.h>int main()
{int a = 3;//00000000000000000000000000000011 - 补码int b = -5;//10000000000000000000000000000101//11111111111111111111111111111010//11111111111111111111111111111011 - 补码int c = a & b;//& -- 对应二进制位有0则为0,两个同时为1,才是1//00000000000000000000000000000011//11111111111111111111111111111011//00000000000000000000000000000011 - 补码printf("%d\n", c);//3return 0;
}
// | 操作符
#include<stdio.h>
int main()
{int a = 3;//00000000000000000000000000000011 - 补码int b = -5;//10000000000000000000000000000101//11111111111111111111111111111010//11111111111111111111111111111011 - 补码int c = a | b;// | - 按(2进制)位或 - 对应的二进制位有1则为1,两个同时为0才是0//00000000000000000000000000000011//11111111111111111111111111111011//11111111111111111111111111111011 - 补码//11111111111111111111111111111010//10000000000000000000000000000101 - -5printf("%d\n", c);//-5return 0;
}
// ^ 操作符
#include<stdio.h>
int main()
{int a = 3;//00000000000000000000000000000011 - 补码int b = -5;//10000000000000000000000000000101//11111111111111111111111111111010//11111111111111111111111111111011 - 补码//int c = a ^ b;//^ - 按二进制位异或 -对应的二进制位相同为0,相异为1//00000000000000000000000000000011//11111111111111111111111111111011//11111111111111111111111111111000 - 补码//11111111111111111111111111110111//10000000000000000000000000001000 - -8printf("%d\n", c);//-8return 0;
}

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

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

#include<stdio.h>
int main()
{int a = 3;int b = 5;//交换int tmp = a;//临时变量 tmpa = b;b = tmp;printf("交换前:a=%d b=%d\n", a, b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}

🍤 运行结果:

在这里插入图片描述

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

方法一:


#include<stdio.h>
int main()
{int a = 3;int b = 5;a = a + b;b = a - b;a = a - b;printf("交换前:a=%d b=%d\n", a, b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}

🍤 运行结果:

在这里插入图片描述

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

#include<stdio.h>
int main()
{int a = 3;int b = 5;printf("交换前:a=%d b=%d\n", a, b);a = a ^ b;b = a ^ b;a = a ^ b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}

🍤 运行结果:

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

//a^a -> 0
//a^0 = a
#include<stdio.h>int main()
{int a = 3;int b = 5;int c= a^b^a;int d= a^a^b;printf("%d %d\n", c, d);return 0;
}

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

同样地,a^a^b=a

🍤 运行结果:

在这里插入图片描述

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

//方法1
#include <stdio.h>
int main()
{int num = 10;int count = 0;//计数while (num){if (num % 2 == 1)count++;num = num / 2;}printf("二进制中1的个数 = %d\n", count);return 0;
}
//方法2:
#include<stdio.h>
int main()
{int num = -1;int i = 0;int count = 0;//计数for (i = 0; i < 32; i++){if (num & (1 << i))count++;}printf("二进制中1的个数 = %d\n", count);return 0;
}
//方法3,优化版本
#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;
}

5. 赋值操作符

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

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

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

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

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

x = y+1;
a = x;

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

复合赋值符

+= 
-=
*=
/=
%=
>>=
<<=
&=
|=
^=

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

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

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

6. 单目操作符

6.1 单目操作符介绍

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

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

实例1:

// ! 操作符
//非 0 为真
#include<stdio.h>
int main()
{int flag = 5;if (flag == 0){printf("hehe\n");}if (!flag)//这里当 flag 为假时,才会打印hehe{printf("hehe\n");}if (flag){printf("haha\n");}return 0;
}

🍤 运行结果:

在这里插入图片描述

实例2: -

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

🍤 运行结果:

在这里插入图片描述

实例3: &

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

🍤 运行结果:

在这里插入图片描述

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

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

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

实例5: ~

// ~ 按补码二进制位取反
#include<stdio.h>
int main()
{int a = 0;printf("%d\n", ~a);//00000000000000000000000000000000//11111111111111111111111111111111 - 补码//11111111111111111111111111111110//10000000000000000000000000000001 -1return 0;
}

🍤 运行结果:

在这里插入图片描述

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

//前置++:先对变量进行自增,然后使用该变量
int main()
{int a = 1;int b = ++a;//前置++,先++,后使用//a=a+1,b=aprintf("a=%d b=%d\n", a, b);//2 2return 0;
}

🍤 运行结果:

在这里插入图片描述

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

🍤 运行结果:

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

6.2 sizeof 和 数组

实例:

#include <stdio.h>
void test1(int arr[])
{printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{printf("%d\n", sizeof(ch));//(4)
}
int main()
{int arr[10] = { 0 };char ch[10] = { 0 };printf("%d\n", sizeof(arr));//(1)printf("%d\n", sizeof(ch));//(3)test1(arr);test2(ch);return 0;
}

🍤 运行结果:

在这里插入图片描述

7. 关系操作符

>
>=
<
<=
!=   用于测试“不相等”
==      用于测试“相等”

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

实例:判断闰年

#include<stdio.h>
int main()
{int y = 0;scanf("%d", &y);//1. 能被4整除,并且不能被100整除//2. 能被400整除是闰年if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)){printf("闰年\n");}else{printf("不是闰年\n");}return 0;
}

8. 逻辑操作符

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

实例1:

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

🍤 运行结果:

在这里插入图片描述

实例2:

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

🍤 运行结果:

在这里插入图片描述

9. 条件操作符

exp1 ? exp2 : exp3

实例:

//如果 a>5,则 b=3
//如果 a<=5,则 b=-3
if (a > 5)b = 3;
elseb = -3;

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

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

🍤 运行结果:

在这里插入图片描述

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

#include <stdio.h>
int main()
{int a, b ;scanf("%d %d", &a, &b);int c = a > b ? a : b;printf("%d\n", c);return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/10121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Excel双向柱状图的绘制

Excel双向柱状图在绘制增减比较的时候经常用到&#xff0c;叫法繁多&#xff0c;双向柱状图、上下柱状图、增减柱状图都有。 这里主要介绍一下Excel的基础绘制方法和复杂一点的双向柱状图的绘制 基础双向柱状图的绘制 首先升降的数据如下&#xff1a; 月份上升下降20220359-…

如何创建高级 CSS 下拉菜单

效果展示 实现思路及部分代码 1、定义整体页面结构 从上述的效果展示图可以看出&#xff0c;页面的整体结构应该需要一个总菜单容器来装载父级菜单项&#xff0c;并且对应的父级菜单项应该有对应的菜单子项。子菜单是分类的话&#xff0c;我们还需要额外在扩展对应的容器来装…

代码随想录算法训练营day11 | 20. 有效的括号,1047. 删除字符串中的所有相邻重复项

目录 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值 20. 有效的括号 难度&#xff1a;easy 类型&#xff1a;栈与队列 思路&#xff1a; 利用栈来做括号匹配&#xff1b; 代码&#xff1a; class Solution {public boolean isValid(String…

Flutter 最佳实践和编码准则

Flutter 最佳实践和编码准则 视频 前言 最佳实践是一套既定的准则&#xff0c;可以提高代码质量、可读性和可靠性。它们确保遵循行业标准&#xff0c;鼓励一致性&#xff0c;并促进开发人员之间的合作。通过遵循最佳实践&#xff0c;代码变得更容易理解、修改和调试&#xff…

vue中Cascader 级联选择器实现-修改实现

vue 的cascader研究了好长时间&#xff0c;看了官网给的示例&#xff0c;上网查找了好多信息&#xff0c;才解决修改时回显的问题&#xff0c;现将方法总结如下&#xff1a; vue代码&#xff1a; <el-form-item label"芯片" prop"firmware"> <…

【C# 数据结构】Heap 堆

【C# 数据结构】Heap 堆 先看看C#中有那些常用的结构堆的介绍完全二叉树最大堆 Heap对类进行排序实现 IComparable<T> 接口 对CompareTo的一点解释 参考资料 先看看C#中有那些常用的结构 作为 数据结构系类文章 的开篇文章&#xff0c;我们先了解一下C# 有哪些常用的数据…

系统架构设计师 10:软件架构的演化和维护

一、软件架构演化 如果软件架构的定义是 SA{components, connectors, constraints}&#xff0c;也就是说&#xff0c;软件架构包括组件、连接件和约束三大要素&#xff0c;这类软件架构演化主要关注的就是组件、连接件和约束的添加、修改与删除等。 二、面向对象软件架构演化…

[oeasy]python0075_删除变量_del_delete_variable

删除变量 回忆上次内容 上次我们研究了字节序 字节序有两种 符号英文名称中文名称<little-endian小字节序>big-endian大字节序 字节序 用来 明确 整型数字存储的 顺序 如果 读写数字出了错 可以 考虑一下 是否 字节序出了问题 变量现在可以 声明初始化存储了 但是 …

Spring Boot中整合MyBatis(基于xml方式基于注解实现方式)

一、前提准备 在Spring Boot中整合MyBatis时&#xff0c;你需要导入JDBC&#xff08;不需要手动添加&#xff09;和Druid的相关依赖。 JDBC依赖&#xff1a;在Spring Boot中整合MyBatis时&#xff0c;并不需要显式地添加JDBC的包依赖。这是因为&#xff0c;当你添加mybatis-sp…

i.MX6ULL(二十) linux platform 设备驱动

Linux 系统要考虑到驱动的可重用性&#xff0c;因 此提出了驱动的分离与分层这样的软件思路&#xff0c;在这个思路下诞生了我们将来最常打交道的 platform 设备驱动&#xff0c;也叫做平台设备驱动。 1 Linux 驱动的分离与分层 1.1 驱动的分隔与分离 对于 Linux 这样一…

kubesphere安装中间件

kubesphere安装mysql 创建configMap [client] default-character-setutf8mb4[mysql] default-character-setutf8mb4[mysqld] init_connectSET collation_connection utf8mb4_unicode_ci init_connectSET NAMES utf8mb4 character-set-serverutf8mb4 collation-serverutf8mb4_…

macOS Monterey 12.6.8 (21G725) Boot ISO 原版可引导镜像

macOS Monterey 12.6.8 (21G725) Boot ISO 原版可引导镜像 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Lin…

C# 翻转二叉树

226 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;…

水文章——推荐一个视频播放器和一个图片查看器

视频播放器——PotPlayer http://www.potplayercn.com/ 图片查看器——JPEGVIEW https://www.bilibili.com/video/BV1ZY411P7fX/?spm_id_from333.337.search-card.all.click&vd_sourceab35b4ab4f3968642ce6c3f773f85138

wireshark导出H264裸流

导出H264裸流 安装wireshark下载rtp_h264_extractor.lua脚本配置lua脚本重启wireshark筛选 安装wireshark 下载抓包工具&#xff1a;首先&#xff0c;您需要下载并安装一个网络抓包工具&#xff0c;例如Wireshark&#xff08;https://www.wireshark.org&#xff09;或tcpdump&…

FTP服务器的搭建和配置上传脚本

文章目录 前言一、配置本地用户可上传权限ftp服务器1、用户登录ftp 二、配置FTP上传脚本文件1.脚本代码如下 补充知识 前言 vsftpd&#xff08;Very Secure FTP Daemon&#xff09;是一个在 Linux/Unix 系统上运行的一款开源免费的 FTP 服务器软件。vsftpd 支持支持 匿名用户、…

html2Canvas+jsPDF 下载PDF 遇到跨域的对象存储的图片无法显示

一、问题原因 对象存储的域名和你网址的域名不一样&#xff0c;此时用Canvas相关插件 将DOM元素转化为PDF&#xff0c;就会出现跨域错误。 二、解决办法 两步 1. 图片元素上设置属性 crossorigin"anonymous" 支持原生img和eleme组件 2. 存储桶设置资源跨域访问…

Python - Opencv + pyzbar实时摄像头识别二维码

直接上代码&#xff1a; import cv2 from pyzbar.pyzbar import decodecap cv2.VideoCapture(0) # 打开摄像头while True: # 循环读取摄像头帧ret, frame cap.read()# 在循环中&#xff0c;将每一帧作为图像输入&#xff0c;使用pyzbar的decode()函数识别二维码barcodes …

MFC表格控件CListCtrl的改造及用法

1、目的 简单描述MFC的表格控件使用方法。Qt适用习惯了以后MFC用的比较别扭&#xff0c;因此记录一下以备后续复制代码使用。由于MFC原生的CListCtrl比较局限&#xff0c;比如无法改变表格的背景色、文字颜色等设定&#xff0c;因此先对CListCtrl类进行重写&#xff0c;以便满足…

Carla教程一:动力学模型到LQR

Carla教程一、动力学模型到LQR 从运动学模型和动力学模型到LQR 模型就是可以描述车辆运动规律的模型。车辆建模都是基于自行车模型的设定,也就是将四个轮子抽象为自行车一样的两个轮子来建模。 1、运动学模型 运动学模型是基于几何关系分析出来的,一般适用于低俗情况下,…