【C/C++】事件驱动架构中,高性能位移操作事件状态位的优势

news/2024/12/16 17:32:26/

你提到的两个操作 combined_events ^= EVENT_ONE;combined_events &= ~EVENT_ONE; 是位操作中非常常见的两种方式,分别用于切换标志的状态清除标志。下面我们详细解释这两种操作的工作原理,并通过具体的例子来说明它们是如何处理的。

1. 切换标志的状态

工作原理:
  • 按位异或 (^) 操作:按位异或操作符会逐位比较两个操作数。如果对应的两位不同,则结果为 1;如果相同,则结果为 0。
  • 效果:当某个标志已经设置时,^= 会将其清除;当某个标志未设置时,^= 会将其设置。因此,^= 可以用来切换标志的状态
举例说明:

假设我们有一个变量 combined_events,它表示多个事件的组合。我们定义了以下枚举成员:

enum EventFlags {EVENT_ONE   = 1 << 0,  // 0001 (二进制)EVENT_TWO   = 1 << 1,  // 0010 (二进制)EVENT_THREE = 1 << 2,  // 0100 (二进制)
};

假设当前 combined_events 的值为 0101(即 EVENT_ONE | EVENT_THREE),表示 EVENT_ONEEVENT_THREE 都被设置了。

  • 切换 EVENT_ONE 的状态
combined_events ^= EVENT_ONE;
  • 执行前combined_events = 0101(二进制)
  • 执行后combined_events = 0100(二进制)

解释:

  • 0101 ^ 0001 = 0100
  • EVENT_ONE 的状态从“已设置”切换为“未设置”。

如果我们再次执行 combined_events ^= EVENT_ONE;,则 EVENT_ONE 的状态将再次切换回“已设置”:

  • 执行前combined_events = 0100(二进制)
  • 执行后combined_events = 0101(二进制)

解释:

  • 0100 ^ 0001 = 0101
  • EVENT_ONE 的状态从“未设置”切换为“已设置”。
小概括下:
  • combined_events ^= EVENT_ONE;切换 EVENT_ONE 的状态。如果 EVENT_ONE 已经设置,则将其清除;如果未设置,则将其设置。

2. **清除标志:combined_events &= ~EVENT_ONE;

工作原理:
  • 按位与 (&) 操作:按位与操作符会逐位比较两个操作数。只有当两个操作数的对应位都为 1 时,结果才为 1;否则结果为 0。
  • 按位非 (~) 操作:按位非操作符会将操作数的每一位取反。0 变为 1,1 变为 0。
  • 效果~EVENT_ONE 会生成一个所有位都为 1 的值,除了 EVENT_ONE 对应的那一位是 0。然后通过 &= 操作,将 combined_eventsEVENT_ONE 对应的位清零,而其他位保持不变。因此,&= ~EVENT_ONE 可以用来清除 EVENT_ONE 标志
举例说明:

继续使用上面的例子,假设 combined_events 的值为 0101(即 EVENT_ONE | EVENT_THREE),表示 EVENT_ONEEVENT_THREE 都被设置了。

  • 清除 EVENT_ONE
combined_events &= ~EVENT_ONE;
  • 执行前combined_events = 0101(二进制)
  • 执行后combined_events = 0100(二进制)

解释:

  • ~EVENT_ONE = 1110(二进制)
  • 0101 & 1110 = 0100
  • EVENT_ONE 的状态被清除,但 EVENT_THREE 保持不变。
总结:
  • combined_events &= ~EVENT_ONE;清除 EVENT_ONE 的状态,而不会影响其他标志的状态。

3. 对比与选择

  • ^= 操作:用于切换标志的状态。如果你不确定某个标志是否已经设置,或者你希望在已设置和未设置之间来回切换,^= 是最合适的选择。

    • 优点:可以灵活地切换标志的状态,适合需要动态控制的情况。
    • 缺点:无法直接指定是要设置还是清除标志,只能切换。
  • &= ~ 操作:用于清除标志。如果你明确知道要清除某个标志,而不影响其他标志,&= ~ 是最合适的选择。

    • 优点:可以直接清除某个标志,而不会影响其他标志。
    • 缺点:无法设置标志,只能清除。

4. 设置标志的操作

如果我们想设置某个标志,可以使用按位或 (|) 操作:

combined_events |= EVENT_ONE;
  • 效果:如果 EVENT_ONE 未设置,则将其设置;如果已经设置,则保持不变。
举例:

假设 combined_events 的值为 0100(即 EVENT_THREE 被设置),执行 combined_events |= EVENT_ONE; 后:

  • 执行前combined_events = 0100(二进制)
  • 执行后combined_events = 0101(二进制)

解释:

  • 0100 | 0001 = 0101
  • EVENT_ONE 被设置,EVENT_THREE 保持不变。

5. 开发过程中 的使用

操作作用示例
combined_events ^= EVENT_ONE;切换 EVENT_ONE 的状态如果已设置则清除,未设置则设置
combined_events &= ~EVENT_ONE;清除 EVENT_ONE仅清除 EVENT_ONE,不影响其他标志
`combined_events= EVENT_ONE;`设置 EVENT_ONE
  • 切换标志:当你需要在已设置和未设置之间来回切换某个标志时,使用 ^=
  • 清除标志:当你明确知道要清除某个标志,且不希望影响其他标志时,使用 &= ~
  • 设置标志:当你明确知道要设置某个标志,且不希望影响其他标志时,使用 |=

6. 开发的代码示例

下面是一个完整的代码示例,展示了如何使用这些位操作来设置、清除和切换标志:

#include <stdio.h>enum EventFlags {EVENT_ONE   = 1 << 0,  // 0001 (二进制)EVENT_TWO   = 1 << 1,  // 0010 (二进制)EVENT_THREE = 1 << 2,  // 0100 (二进制)
};void print_events(int events) {printf("Events: ");if (events & EVENT_ONE)   printf("ONE ");if (events & EVENT_TWO)   printf("TWO ");if (events & EVENT_THREE) printf("THREE ");printf("\n");
}int main() {int combined_events = 0;// 设置 EVENT_ONE 和 EVENT_THREEcombined_events |= EVENT_ONE;combined_events |= EVENT_THREE;print_events(combined_events);  // 输出: Events: ONE THREE// 切换 EVENT_ONE 的状态(从设置到未设置)combined_events ^= EVENT_ONE;print_events(combined_events);  // 输出: Events: THREE// 再次切换 EVENT_ONE 的状态(从未设置到设置)combined_events ^= EVENT_ONE;print_events(combined_events);  // 输出: Events: ONE THREE// 清除 EVENT_ONEcombined_events &= ~EVENT_ONE;print_events(combined_events);  // 输出: Events: THREEreturn 0;
}

http://www.ppmy.cn/news/1555632.html

相关文章

opencv——图片矫正

图像矫正 图像矫正的原理是透视变换&#xff0c;下面来介绍一下透视变换的概念。 听名字有点熟&#xff0c;我们在图像旋转里接触过仿射变换&#xff0c;知道仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程&#xff0c;转换过程坐标点的相对位置和属性不发生变换&a…

Spring Boot 配置多数据源并手动配置事务

Spring Boot 配置多数据源并手动配置事务 一、为什么多数据源需要手动配置&#xff1f;二、配置多数据源1. 数据源配置类 (DataSourceConfig)2. 主数据库 MyBatis 配置类 (PrimaryDbMyBatisConfig)3. 从数据库 MyBatis 配置类 (SecondaryDbMyBatisConfig)4. application.yml 配…

【数据分享】2013-2023年我国省市县三级的逐年CO数据(免费获取\excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2023年的省市县三级的逐年PM2.5数据、2000-2023年的省市县三级的逐年PM10数据、2013-2023年的省市县三级的逐年SO2数据、2000-2023年省市县三级的逐年O3数据和2008-2023年我国省市县三级的逐…

MySQL 性能调优:打造高效数据库

SQL 语句层面的性能调优策略 合理选择字段属性 在创建 MySQL 表时&#xff0c;为了获取更好的性能&#xff0c;选择合适的字段属性至关重要。 首先&#xff0c;要依据实际情况合理设置字段的类型及宽度。例如&#xff0c;对于像手机号码这类固定长度为 11 位的字段&#xff…

SpringCloud微服务实战系列:01让SpringCloud项目在你机器上运行起来

目录 项目选型 项目安装-本地运行起来 软件安装&#xff1a; 项目启动&#xff1a; 总结&答疑 项目选型 软件开发&#xff0c;基本上都不会从0开始&#xff0c;一般都是在其他项目或者组件的基础上进行整合优化迭代&#xff0c;站在巨人肩膀上才能看得更远&#xff0c…

.NET MAUI开发的安卓、iOS软件和Java开发的安卓和Swift开发的iOS的区别

1. 开发语言和平台 .NET MAUI&#xff1a; 使用 C# 作为开发语言。通过 .NET 6/7/8 平台编译并打包应用。.NET MAUI 会根据目标平台&#xff08;Android 或 iOS&#xff09;编译和运行不同的本地代码。代码是跨平台的&#xff0c;开发者可以使用相同的代码库为 Android 和 iOS …

什么是战略思想?

古今中外&#xff0c;关于战略是什么&#xff1f;有非常多的理论&#xff0c;也有不同的视角。 中国最早的涉及战略的书籍据传是黄帝所著的《握奇文》&#xff0c;后有较为系统的兵法战略书籍为周朝姜太公&#xff08;亦称姜尚、姜子牙等&#xff09;所著的《六韬》&#xff0c…

关于Python程序消费Kafka消息不稳定问题的处理方法

在使用Python程序消费Kafka消息的过程中&#xff0c;有时会遇到各种不稳定的情况&#xff0c;如自动提交偏移量无效、CommitFailedError错误等。这些问题不仅影响了数据处理的可靠性&#xff0c;还可能导致重复消费或丢失消息。本文将针对这两个常见问题提供详细的解决方案和最…