当前位置: 首页 > news >正文

用 C 语言实现求补码的运算

缘起

前两天程序中需要求一堆参数的补码,一时犯懒,想从CSDN上搜一个勉强能用的代码借鉴一下,结果几乎没有搜到一个靠谱的!这种求补码的操作,用脚趾头想想也应该知道要用C或者C++的位运算来实现呀。结果搜到的一些实现方式竟然是把数值的二进制形式下的位,一位一位地进行操作!这简直离谱到家了,虽然这样做也能从功能上实现求补码的运算,但是性能肯定奇差呀。我们之所以用 C 或者 C++,通常都是对性能有一定的追求,如果你丝毫不在意性能,那你干嘛不去用 C# 或者 Java?

所以还是自己写了几个求补码的函数,分享在这里。本来觉得这是简单得不值一提的东西,但是看来并非人人都能把这件事情做对了。

之所以用 C 实现,而不是用 C++,是因为:(1) C 的函数可以在 C++ 中被无缝调用,反之则不行;(2) 用 C 实现,可以照顾到某些只能用 C 不能用 C++ 的嵌入式环境;(3) 这个实现过程实在是没有必要用到 C++ 的那些面向对象的特性,直接用 C 的过程式编程就足够了。我看到 CSDN 上有一个人实现求补码的过程,居然用到了 C++ 的 vector 容器,而且还对这个容器进行了动态地 insert 的操作,有这个必要吗??

从实际需求出发,我依次实现了对 8 位带符号整数、16 位带符号整数和 32 位带符号整数求补码的函数,以及它们的逆运算的函数。通常我们求补码的时候也不会希望求一个任意二进制字节流的补码,都是对实际的 8 位带符号整数、16 位带符号整数和 32 位带符号整数求补码进行求补码运算的。

原码、反码和补码的基础知识我就不在这里啰嗦了,CSDN 网站上介绍这些知识的文章多得是!我就直接上代码了。

程序实现

统一数据类型

对于 8 位整数、16 位整数和 32 位整数,为了照顾到不同的编译环境,我定义了一堆统一的数据类型,包括:

  1. 8位带符号和无符号整型:int8_t 与 uint8_t;
  2. 16位带符号和无符号整型:int16_t 与 uint16_t;
  3. 32位带符号和无符号整型:int32_t 与 uint32_t;

这些定义我放在了 datatypes.h 这个头文件里,通常我的 C / C++ 程序都会引用这个头文件:

#ifndef _INC_COMMON_datatypes_H
#define _INC_COMMON_datatypes_H#if _MSC_VER && _MSC_VER < 1700
typedef __int8              int8_t;
typedef __int16             int16_t;
typedef __int32             int32_t;
typedef __int64             int64_t;
typedef unsigned __int8     uint8_t;
typedef unsigned __int16    uint16_t;
typedef unsigned __int32    uint32_t;
typedef unsigned __int64    uint64_t;
#else
#include <stdint.h>
#endiftypedef float           float32_t;
typedef double          float64_t;
typedef unsigned char	byte;
typedef char            sbyte;#ifdef _WIN64
#define ssize_t __int64
#else
#define ssize_t long
#endif#endif // !_INC_COMMON_datatypes_H

求补码的函数

头文件里面的函数原型定义:

#include "datatypes.h"#ifdef __cplusplus
extern "C" {
#endif// 求 srcvalue 的8位补码, srcvalue 的取值范围是: [-128(-0x80), +127(+0x7F)]uint8_t I8_to_Complement(int8_t srcvalue);// 求 srcvalue 的16位补码, srcvalue 的取值范围是 : [-32768(-0x8000), +32767(+0x7FFF)]uint16_t I16_to_Complement(int16_t srcvalue);// 求 srcvalue 的32位补码, srcvalue 的取值范围是 : [-2147483648(-0x80000000), +2147483647(+0x7FFFFFFF)]uint32_t I32_to_Complement(int32_t srcvalue);#ifdef __cplusplus
} // ! extern "C"
#endif

函数实现:

// 求 srcvalue 的8位补码, srcvalue 的取值范围是: [-128(-0x80), +127(+0x7F)]
uint8_t I8_to_Complement(int8_t srcvalue)
{uint8_t compcode;if (srcvalue >= 0){compcode = (uint8_t)srcvalue;goto EXIT;}uint8_t tail = (uint8_t)(0 - srcvalue);tail = ~tail;compcode = tail + 1;EXIT:return compcode;
}// 求 srcvalue 的16位补码, srcvalue 的取值范围是 : [-32768(-0x8000), +32767(+0x7FFF)]
uint16_t I16_to_Complement(int16_t srcvalue)
{uint16_t compcode;if (srcvalue >= 0){compcode = (uint16_t)srcvalue;goto EXIT;}uint16_t tail = (uint16_t)(0 - srcvalue);tail = ~tail;compcode = tail + 1;EXIT:return compcode;
}// 求 srcvalue 的32位补码, srcvalue 的取值范围是 : [-2147483648(-0x80000000), +2147483647(+0x7FFFFFFF)]
uint32_t I32_to_Complement(int32_t srcvalue)
{uint32_t compcode;if (srcvalue >= 0){compcode = (uint32_t)srcvalue;goto EXIT;}uint32_t tail = (uint32_t)(0 - srcvalue);tail = ~tail;compcode = tail + 1;EXIT:return compcode;
}

根据补码求原值(即:求补码运算的逆运算)

头文件里面的函数原型定义:

#include "datatypes.h"#ifdef __cplusplus
extern "C" {
#endif// 求8位补码 compcode 的原值int8_t Complement_to_I8(uint8_t compcode);// 求16位补码 compcode 的原值int16_t Complement_to_I16(uint16_t compcode);// 求32位补码 compcode 的原值int32_t Complement_to_I32(uint32_t compcode);#ifdef __cplusplus
} // ! extern "C"
#endif

函数实现:

// 求8位补码 compcode 的原值
int8_t Complement_to_I8(uint8_t compcode)
{int8_t srcvalue;uint8_t head = compcode & 0x80;if (head == 0){srcvalue = (int8_t)compcode;goto EXIT;}uint8_t tail = compcode - 1;tail = ~tail;srcvalue = 0 - (int8_t)tail;EXIT:return srcvalue;
}// 求16位补码 compcode 的原值
int16_t Complement_to_I16(uint16_t compcode)
{int16_t srcvalue;uint16_t head = compcode & 0x8000;if (head == 0){srcvalue = (int16_t)compcode;goto EXIT;}uint16_t tail = compcode - 1;tail = ~tail;srcvalue = 0 - (int16_t)tail;EXIT:return srcvalue;
}// 求32位补码 compcode 的原值
int32_t Complement_to_I32(uint32_t compcode)
{int32_t srcvalue;uint32_t head = compcode & 0x80000000;if (head == 0){srcvalue = (int32_t)compcode;goto EXIT;}uint32_t tail = compcode - 1;tail = ~tail;srcvalue = 0 - (int32_t)tail;EXIT:return srcvalue;
}

程序验证

我找到了一个求原码、反码、补码的在线工具,亲测靠谱,给大家推荐一下网址:https://www.lddgo.net/convert/number-binary-code

我用 CUnit 写了一些单元测试,来验证我上述提供的这些求补码的函数及其逆运算函数的正确性。我就不在这里科普 CUnit 的基本用法了,直接贴相关的单元测试代码。

单元测试程序的头文件

#ifndef _INC_UNITTETST_CUNIT_COMMFUNC_TESTCASES_COMMONFUNC_TS_A001_Common_H
#define _INC_UNITTETST_CUNIT_COMMFUNC_TESTCASES_COMMONFUNC_TS_A001_Common_H#define TS_A001_Identifier "TS_A001: Bit Operation"#ifdef __cplusplus
extern "C" {
#endifint TS_A001_Setup(void);int TS_A001_Cleanup(void);// 验证 I8_to_Complement 函数对输入参数`srcvalue`为0或正整数时工作正常void TC0001_I8_to_Complement_PositiveInteger();// 验证 I8_to_Complement 函数对输入参数`srcvalue`为负整数时工作正常void TC0002_I8_to_Complement_NegativeInteger();// 验证 Complement_to_I8 函数对 TC0001 和 TC0002 中的正/负整数求得的补码,都能逆向求得其原始值(正/负整数)void TC0003_Complement_to_I8();// 验证 I16_to_Complement 函数对输入参数`srcvalue`为0或正整数时工作正常void TC0004_I16_to_Complement_PositiveInteger();// 验证 I16_to_Complement 函数对输入参数`srcvalue`为负整数时工作正常void TC0005_I16_to_Complement_NegativeInteger();// 验证 Complement_to_I16 函数对 TC0004 和 TC0005 中的正/负整数求得的补码,都能逆向求得其原始值(正/负整数)void TC0006_Complement_to_I16();// 验证 I32_to_Complement 函数对输入参数`srcvalue`为0或正整数时工作正常void TC0007_I32_to_Complement_PositiveInteger();// 验证 I32_to_Complement 函数对输入参数`srcvalue`为负整数时工作正常void TC0008_I32_to_Complement_NegativeInteger();// 验证 Complement_to_I32 函数对 TC0007 和 TC0008 中的正/负整数求得的补码,都能逆向求得其原始值(正/负整数)void TC0009_Complement_to_I32();#ifdef __cplusplus
} // ! extern "C"
#endif#endif // !_INC_UNITTETST_CUNIT_COMMFUNC_TESTCASES_COMMONFUNC_TS_A001_Common_H

单元测试程序的测试用例实现

#include "CUnit/CUnit.h"
#include "Common/CommonFuncs.h"#include "TS_A001_Common.h"// ----------------------------------------------------------------------
// Public functions implementation
// ----------------------------------------------------------------------int TS_A001_Setup(void)
{return CUE_SUCCESS;
}int TS_A001_Cleanup(void)
{return CUE_SUCCESS;
}// ========================================================
// 参考:在线原码/反码/补码计算器
// https://www.lddgo.net/convert/number-binary-code
// ========================================================// 验证 I8_to_Complement 函数对输入参数`srcvalue`为0或正整数时工作正常
void TC0001_I8_to_Complement_PositiveInteger()
{
#define TC0001_VARS_COUNT 3int8_t SrcValues[TC0001_VARS_COUNT] = {0, 1, 127};uint8_t CompCodes[TC0001_VARS_COUNT] = {0, 1, 0x7F};for (int idx = 0; idx < TC0001_VARS_COUNT; idx++){uint8_t compcode = I8_to_Complement(SrcValues[idx]);CU_ASSERT_EQUAL(compcode, CompCodes[idx]);}
}// 验证 I8_to_Complement 函数对输入参数`srcvalue`为负整数时工作正常
void TC0002_I8_to_Complement_NegativeInteger()
{
#define TC0002_VARS_COUNT 6int8_t SrcValues[TC0002_VARS_COUNT] = {-1, -3, -63, -64, -127, -128};uint8_t CompCodes[TC0002_VARS_COUNT] = {0xFF, 0xFD, 0xC1, 0xC0, 0x81, 0x80};for (int idx = 0; idx < TC0002_VARS_COUNT; idx++){uint8_t compcode = I8_to_Complement(SrcValues[idx]);CU_ASSERT_EQUAL(compcode, CompCodes[idx]);}
}// 验证 Complement_to_I8 函数对 TC0001 和 TC0002 中的正/负整数求得的补码,都能逆向求得其原始值(正/负整数)
void TC0003_Complement_to_I8()
{
#define TC0003_VARS_COUNT 9int8_t SrcValues[TC0003_VARS_COUNT] = {0, 1, 127,-1, -3, -63, -64, -127, -128};uint8_t CompCodes[TC0003_VARS_COUNT] = {0, 1, 0x7F,0xFF, 0xFD, 0xC1, 0xC0, 0x81, 0x80};for (int idx = 0; idx < TC0003_VARS_COUNT; idx++){int8_t srcValue = Complement_to_I8(CompCodes[idx]);CU_ASSERT_EQUAL(srcValue, SrcValues[idx]);}
}// 验证 I16_to_Complement 函数对输入参数`srcvalue`为0或正整数时工作正常
void TC0004_I16_to_Complement_PositiveInteger()
{
#define TC0004_VARS_COUNT 7int16_t SrcValues[TC0004_VARS_COUNT] = {0, 1, 127, 128, 255,256, 32767};uint16_t CompCodes[TC0004_VARS_COUNT] = {0, 1, 0x7F, 0x80, 0xFF,0x0100, 0x7FFF};for (int idx = 0; idx < TC0004_VARS_COUNT; idx++){uint16_t compcode = I16_to_Complement(SrcValues[idx]);CU_ASSERT_EQUAL(compcode, CompCodes[idx]);}
}// 验证 I16_to_Complement 函数对输入参数`srcvalue`为负整数时工作正常
void TC0005_I16_to_Complement_NegativeInteger()
{
#define TC0005_VARS_COUNT 12int16_t SrcValues[TC0005_VARS_COUNT] = {-1, -3, -63, -64, -127, -128, -129, -255, -256,-257,-32767, -32768};uint16_t CompCodes[TC0005_VARS_COUNT] = {0xFFFF, 0xFFFD, 0xFFC1, 0xFFC0, 0xFF81, 0xFF80, 0xFF7F, 0xFF01, 0xFF00,0xFEFF,0x8001, 0x8000};for (int idx = 0; idx < TC0005_VARS_COUNT; idx++){uint16_t compcode = I16_to_Complement(SrcValues[idx]);CU_ASSERT_EQUAL(compcode, CompCodes[idx]);}
}// 验证 Complement_to_I16 函数对 TC0004 和 TC0005 中的正/负整数求得的补码,都能逆向求得其原始值(正/负整数)
void TC0006_Complement_to_I16()
{
#define TC0006_VARS_COUNT 19int16_t SrcValues[TC0006_VARS_COUNT] = {0, 1, 127, 128, 255,256, 32767,-1, -3, -63, -64, -127, -128, -129, -255, -256,-257,-32767, -32768};uint16_t CompCodes[TC0006_VARS_COUNT] = {0, 1, 0x7F, 0x80, 0xFF,0x0100, 0x7FFF,0xFFFF, 0xFFFD, 0xFFC1, 0xFFC0, 0xFF81, 0xFF80, 0xFF7F, 0xFF01, 0xFF00,0xFEFF,0x8001, 0x8000};for (int idx = 0; idx < TC0006_VARS_COUNT; idx++){int16_t srcValue = Complement_to_I16(CompCodes[idx]);CU_ASSERT_EQUAL(srcValue, SrcValues[idx]);}
}// 验证 I32_to_Complement 函数对输入参数`srcvalue`为0或正整数时工作正常
void TC0007_I32_to_Complement_PositiveInteger()
{
#define TC0007_VARS_COUNT 3int32_t SrcValues[TC0007_VARS_COUNT] = {0, 1, 0x7FFFFFFF};uint32_t CompCodes[TC0007_VARS_COUNT] = {0, 1, 0x7FFFFFFF};for (int idx = 0; idx < TC0007_VARS_COUNT; idx++){uint32_t compcode = I32_to_Complement(SrcValues[idx]);CU_ASSERT_EQUAL(compcode, CompCodes[idx]);}
}// 验证 I32_to_Complement 函数对输入参数`srcvalue`为负整数时工作正常
#if defined(_WIN32) && defined(_MSC_VER)
#pragma warning(disable: 4146)
#endif
void TC0008_I32_to_Complement_NegativeInteger()
{
#define TC0008_VARS_COUNT 4// 2147483647(DEC): 0x7FFFFFFF// 2147483648(DEC): 0x80000000int32_t SrcValues[TC0008_VARS_COUNT] = {-1, -2, -2147483647, -2147483648};uint32_t CompCodes[TC0008_VARS_COUNT] = {0xFFFFFFFF, 0xFFFFFFFE, 0x80000001, 0x80000000};for (int idx = 0; idx < TC0008_VARS_COUNT; idx++){uint32_t compcode = I32_to_Complement(SrcValues[idx]);CU_ASSERT_EQUAL(compcode, CompCodes[idx]);}
}// 验证 Complement_to_I32 函数对 TC0007 和 TC0008 中的正/负整数求得的补码,都能逆向求得其原始值(正/负整数)
#if defined(_WIN32) && defined(_MSC_VER)
#pragma warning(disable: 4146)
#endif
void TC0009_Complement_to_I32()
{
#define TC0009_VARS_COUNT 7int32_t SrcValues[TC0009_VARS_COUNT] = {0, 1, 0x7FFFFFFF,-1, -2, -2147483647, -2147483648};uint32_t CompCodes[TC0009_VARS_COUNT] = {0, 1, 0x7FFFFFFF,0xFFFFFFFF, 0xFFFFFFFE, 0x80000001, 0x80000000};for (int idx = 0; idx < TC0009_VARS_COUNT; idx++){int32_t srcValue = Complement_to_I32(CompCodes[idx]);CU_ASSERT_EQUAL(srcValue, SrcValues[idx]);}
}

单元测试的运行结果

通过单元测试,验证了程序的正确性。截图如下:
在这里插入图片描述
在这里插入图片描述

相关文章:

用 C 语言实现求补码的运算

缘起 前两天程序中需要求一堆参数的补码&#xff0c;一时犯懒&#xff0c;想从CSDN上搜一个勉强能用的代码借鉴一下&#xff0c;结果几乎没有搜到一个靠谱的&#xff01;这种求补码的操作&#xff0c;用脚趾头想想也应该知道要用C或者C的位运算来实现呀。结果搜到的一些实现方…...

python下载文件

import urllib.request url "http://****/storage/x4MigEhU6BGAuTqjrRfIBky0S2aMmkyGl4UzTqUb.png"#下载地址 path "ddad.png"#保存路径&#xff0c;保存项目路径 urllib.request.urlretrieve(url, path)...

JMU 数科 数据库与数据仓库期末总结(1)

本章根据老师给出的知识点作进一步相对生动一点的解释。 不保证完全正确。 先给出总的知识点&#xff0c;再给出生动解释。 知识点 数据模型通常由三部分组成&#xff1a;数据结构、数据操作和完整性约束。关系模式中主码的取值必须唯一且非空&#xff0c;这是实体完整性的…...

前端问题整理

Vue vue mvvm&#xff08;Model-View-ViewModel&#xff09;架构模式原理 Model 是数据层&#xff0c;即 vue 实例中的数据View 是视图层&#xff0c; 即 domViewModel&#xff0c;即连接Model和Vue的中间层&#xff0c;Vue实例就是ViewModelViewModel 负责将 Model 的变化反映…...

【实践功能记录6】表格列悬浮展示tooltip信息

需求描述&#xff1a; 鼠标悬浮在表格的IP字段上时&#xff0c;使用tooltip展示IP信息&#xff0c;如图&#xff1a; 1.封装根据IP展示信息的组件 请求接口获取IP信息&#xff0c;注意请求接口时防抖 <!-- 根据IP展示资产信息 --> <template><div><el-…...

AI论文速读 | 2024[SIGIR]基于大语言模型的下一个兴趣点推荐

论文标题&#xff1a;Large Language Models for Next Point-of-Interest Recommendation 作者&#xff1a;Peibo Li ; Maarten de Rijke ; Hao Xue &#xff08;薛昊&#xff09;; Shuang Ao ; Yang Song ; Flora D. Salim 机构&#xff1a;新南威尔士大学(UNSW)&#xff0c…...

Rust 实战丨通过实现 json! 掌握声明宏

在 Rust 编程语言中&#xff0c;宏是一种强大的工具&#xff0c;可以用于在编译时生成代码。json! 是一个在 Rust 中广泛使用的宏&#xff0c;它允许我们在 Rust 代码中方便地创建 JSON 数据。 声明宏&#xff08;declarative macros&#xff09;是 Rust 中的一种宏&#xff0…...

vue+elementUI实现在表格中添加输入框并校验的功能

背景&#xff1a; vue2elmui 需求&#xff1a; 需要在一个table中添加若干个输入框&#xff0c;并且在提交时需要添加校验 思路&#xff1a; 当需要校验的时候可以考虑添加form表单来触发校验&#xff0c;因此需要在table外面套一层form表单&#xff0c;表单的属性就是ref…...

为国产加油:“缺芯少屏”暂缓,另一领域,也要加把劲

说起咱中国之前的“缺芯少屏”&#xff0c;真的是让人挺闹心的。 不过呢&#xff0c;为了改变这个状况&#xff0c;咱们的工程师们可是费了不少劲儿&#xff0c;辛辛苦苦努力了数十年。现在好了&#xff0c;咱们也迎来了柔性屏的时代。 柔性屏 说起来&#xff0c;在触摸屏或者…...

【Qnx】Qnx coredump解析

Qnx coredump解析 coredump文件 Qnx运行的程序崩溃时&#xff0c;会生成coredump文件。 默认情况下这些文件默认会保存在/var/log/*.core 文件中。 解析coredump文件&#xff0c;可以帮忙加快分析程序崩溃的原因&#xff0c;比如了解崩溃的堆栈。 通常可以使用gdb和coreinfo…...

超级签名源码/超级签/ios分发/签名端本地linux服务器完成签名

该系统完全在linux下运行&#xff0c;不存在使用第三方收费工具&#xff0c;市面上很多系统都是使用的是第三方收费系统&#xff0c;例如&#xff1a;某心签名工具&#xff0c;某测侠等&#xff0c;不开源而且需要每年交费&#xff0c;这种系统只是在这些工具的基础上套了一层壳…...

RocketMQ在Centos7系统上单机部署

最近因为一些信创问题&#xff0c;要将RabbitMQ替换为RocketMQ&#xff0c;因此在此分享一些RocketMQ在Centos7系统上单机部署相关过程。 优缺点 RocketMQ的优点&#xff1a; 性能优越&#xff1a;RocketMQ在处理大量消息时&#xff0c;性能优于RabbitMQ。当面临每秒数万到数…...

Vue37-非单文件组件

一、组件的两种编写形式&#xff1a; 非单文件组件&#xff1b;单文件组件。 二、创建一个组件 2-1、组件中的el 组件中不写el&#xff0c;不说为谁服务。 2-2、组件中的data 因为对象形式&#xff0c;多处复用的话&#xff0c;有引用关系&#xff0c;改一处&#xff0c;另一…...

CSS实现经典打字小游戏《生死时速》

&#x1f33b; 前言 CSS 中有这样一个模块&#xff1a;Motion Path 运动模块&#xff0c;它可以使元素按照自定义的路径进行移动。本文将为你讲解这个模块属性的使用&#xff0c;并且利用它实现我小时候电脑课经常玩的一个打字游戏&#xff1a;金山打字的《生死时速》。 &…...

推箱子-小游戏

学习目标&#xff1a; 巩固Java基础&#xff0c;数据类型、二维数组、条件语句等&#xff1b; 效果展示&#xff1a;...

AI数字人的开源解决方案

目前&#xff0c;国内外已经涌现出一些优秀的数字人开源解决方案&#xff0c;这些解决方案为开发者提供了构建数字人应用的工具和基础设施。以下是一些比较知名的数字人开源解决方案。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1…...

java写一个验证码

生成验证码 内容&#xff1a;可以是小写字母&#xff0c;也可以是大写字母&#xff0c;还可以是数字 规则 长度为5 内容中是四位字母&#xff0c;1位数字。 其中数字只有1位&#xff0c;但是可以出现在任意的位置。 package User;import java.util.ArrayList; import jav…...

【星海随笔】ELK优化

ELS 再遇到大的日志文件的时候不会自动进行清理的,我们可以通过 logrotate 转储工具进行操作。 该命令是基于 Cron 实现,由系统执行,当然也可以手动进行执行例如 logrotate -f configfile# more /etc/logrotate.confweekly // 默认每一周执行一次rotate轮转工作 r…...

SQL Auto Increment

SQL Auto Increment 在关系型数据库中&#xff0c;自动增量&#xff08;Auto Increment&#xff09;是一个常见且实用的特性。它允许数据库自动为表中插入的新行分配唯一的标识符&#xff0c;通常用于主键字段。本文将深入探讨SQL中的自动增量功能&#xff0c;包括其工作原理、…...

网络安全练气篇——PHP编程语言基础

目录 PHP基础 一、PHP简介与环境搭建 什么是PHP&#xff1f; PHP环境安装 代码编辑选择 二、基本语法 PHP基本语法操作 PHP变量与输出 啥是常量? PHP注释 PHP单引号双引号声明 三、PHP表单 PHP表单 四、登录界面搭建与讲解 构建登陆页面 登陆页面端 服务器端…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

Mysql故障排插与环境优化

前置知识点 最上层是一些客户端和连接服务&#xff0c;包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念&#xff0c;为通过安全认证接入的客户端提供线程。同样在该层上可…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...