win7系统做asp网站,企业logo设计思路,wordpress静态,个人作品集模板免费缘起
前两天程序中需要求一堆参数的补码#xff0c;一时犯懒#xff0c;想从CSDN上搜一个勉强能用的代码借鉴一下#xff0c;结果几乎没有搜到一个靠谱的#xff01;这种求补码的操作#xff0c;用脚趾头想想也应该知道要用C或者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 位整数为了照顾到不同的编译环境我定义了一堆统一的数据类型包括
8位带符号和无符号整型int8_t 与 uint8_t16位带符号和无符号整型int16_t 与 uint16_t32位带符号和无符号整型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]);}
}
单元测试的运行结果
通过单元测试验证了程序的正确性。截图如下