如何编写完全可移植的 4 字节字符常量的编译时初始化

2024-05-10

(遗留)代码大致如下所示。

#define MAKEID(a,b,c,d) (((UInt32)a)<<24 | ((UInt32)b)<<16 
                        | ((UInt32)c)<<8 | ((UInt32)d) )
#define ID_FORM MAKEID('F','O','R','M')
//...
struct S { 
  int id;
  int x;
  double d;
  // other stuff
};
//...
S s;
socket.read(&s, sizeof(s));  // read network data over struct
if (s.id == ID_FORM) { }

该代码将字符流读入结构中。 S.id 是一个 4 字符常量,例如按流(网络)顺序排列的“FORM”或“DATA”,它决定了结构其余部分的布局。所有比较都是使用预定义常量的整数。

MAKEID 宏是大端字节序,因为它将第一个(字符)参数放置在最高有效字节,这也是最低的内存地址。宏的小端版本如下所示,将第一个(字符)参数放置在最低有效字节处,即现在的最低内存地址。

 #define MAKEID(a,b,c,d) (((UInt32)d)<<24 | ((UInt32)c)<<16 
                        | ((UInt32)b)<<8 | ((UInt32)a) )

问题是如何重写它,以便它在大端和小端架构上同样有效。

不,我不想编写两个宏并使用 #ifdef 选择哪个宏。代码中的任何地方都没有其他字节序依赖关系,我不想在这里介绍一个。便携式是必经之路。

不,我不想写函数。这个常量用在函数不能去的地方。我编写了一个初始化联合的可移植函数,但代码无法编译。

我正在寻找任何类型的可移植宏或模板来进行编译时初始化。

在回答评论时,这是真正的代码。它是网络协议的一部分,另一端在大多数情况下负责处理字节序。这恰好是一个例外,另一端以网络字节顺序生成,而这一端历史上被编写为大尾数作为 4 字节字符常量,如“FORM”。我需要一种单点解决方案,而不是一种将字节序思想传播到代码中其他地方的解决方案。


Your MAKEID宏与字节序无关。它在大端和小端系统上的工作方式相同。

该宏可能看起来是特定于大端的,但 C++ 中的移位和按位或运算都是根据它们对所操作的值的结果来定义的,而不是这些值的底层存储。
Doing 42 << 24保证投入价值42位于结果的最高有效 8 位中,无论字节顺序如何。对于按位或运算也类似。这意味着结果MAKEID(0x12, 0x34, 0x56, 0x78)总是0x12345678,无论底层存储的字节顺序如何。

如果您想生成一个其底层存储始终具有相同位模式的整数(例如 0x12、0x34、0x56、0x78),那么您确实必须重新考虑您的方法。这样的整数将具有以下值0x12345678在大端系统上,0x78563412在小端系统上,也许0x56781234在中端系统上。
但是,如果该位模式是通过使用特定字节顺序(例如大端/网络字节顺序)定义的通信接口接收的,则您必须将收到的任何多字节值转换为系统的本机字节如果您希望接收系统正确解释这些值并且其中包括四字节 ID 值,请排序。

这就是为什么我在答案的早期版本中说,如果您发现在某些系统上(特别是系统的字节顺序与通信的字节顺序不匹配的系统),从流中读取的 ID 与结果不匹配的MAKEID,那么罪魁祸首可能是反序列化代码。 (反)序列化代码是考虑字节顺序的最重要的地方。例如,将您期望的结构覆盖在您收到的字节上很容易,但如果可能存在字节顺序不匹配或填充差异,则这是错误的解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何编写完全可移植的 4 字节字符常量的编译时初始化 的相关文章

  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • C++ 长 switch 语句还是用地图查找?

    在我的 C 应用程序中 我有一些值充当代表其他值的代码 为了翻译代码 我一直在争论使用 switch 语句还是 stl 映射 开关看起来像这样 int code int value switch code case 1 value 10 b
  • 将完整模板参数值映射到原始类型

    我想将数字映射到类型 在这个例子中 我将创建一个函数 将 sizeof 结果映射到有符号的原始类型 我想知道是否有更好的方法来完成我在现代 C 中所做的事情 即采用模板化值并将其转换为类型 现在 这可以将大小转换为已知类型 但我似乎无法在标
  • 解析 JWT 令牌以仅获取有效负载内容,无需 C# 或 Blazor 中的外部库

    我正在使用 Blazor 编写可以访问 JWT 的客户端应用程序 我想知道一种简单的方法来读取令牌有效负载内容而不添加额外的依赖项 因为我不需要其他信息 也不需要验证令牌 我认为解析有效负载内容应该足够简单 只需将其写入方法即可 JwtTo
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 检测到堆栈崩溃

    我正在执行我的 a out 文件 执行后 程序运行一段时间 然后退出并显示消息 stack smashing detected a out terminated Backtrace lib tls i686 cmov libc so 6 f
  • 计算另一个表达式中的 C# 表达式

    我想在另一个表达式中使用一个表达式 Expression
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 如何从 Rx Subscribe 回调异步函数?

    我想回调 Rx 订阅中的异步函数 例如 像那样 public class Consumer private readonly Service service new Service public ReplaySubject
  • 使用 jQuery 从 ASP.Net JSON 服务获取数据

    我正在尝试调用 Google 地图地理编码 API 从纬度 经度对中获取格式化的地址 然后将其记录到控制台 我正在尝试获取为给定位置返回的第一个 formatted address 项目 我很简单无法从 JSON 中提取该项目 我不知道为什
  • CUDA 8 编译错误 -std=gnu++11

    我正在尝试转换一些代码以使用 CUDA 并且我认为我遇到了兼容性问题 我们使用CMake 这些是我使用的 gcc 和 CUDA 版本 gcc version gcc Ubuntu 5 4 0 6ubuntu1 16 04 5 5 4 0 2
  • LINQ 中的“from..where”或“FirstOrDefault”

    传统上 当我尝试从数据库中获取用户的数据时 我使用了以下方法 在某种程度上 DbUsers curUser context DbUsers FirstOrDefault x gt x u LoginName id string name c
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan

随机推荐

  • 曲线/路径骨架二值图像处理

    我正在尝试开发一个可以处理图像骨架的路径 曲线的代码 我想要一个来自两点之间骨架的点向量 该代码在添加一些点后结束 我没有找到解决方案 include opencv2 highgui highgui hpp include opencv2
  • OpenCV 仅围绕大轮廓绘制矩形?

    第一次发帖 希望我以正确的方式放置代码 我正在尝试检测和计算视频中的车辆 因此 如果您查看下面的代码 我会在阈值处理和膨胀后找到图像的轮廓 然后我使用 drawContours 和矩形在检测到的轮廓周围绘制一个框 我试图在 drawCont
  • DOMDocument PHP 内存泄漏

    在 MAC 上的 MAMP 下运行 PHP 5 3 6 内存使用量每调用 x 次 3 到 8 次 就会增加 直到脚本因内存耗尽而终止 我该如何解决 libxml use internal errors true while true dom
  • 使用Python重命名目录中的多个文件

    我正在尝试使用以下 Python 脚本重命名目录中的多个文件 import os path Users myName Desktop directory files os listdir path i 1 for file in files
  • ARMv8 A64 汇编中立即值的范围

    我的理解是 ARMv8 A64 汇编中的立即参数可以是 12 位长 如果是这样的话 为什么这行汇编代码是 AND X12 X10 0xFEF 产生此错误 使用 gcc 编译时 Error immediate out of range at
  • 日期时间解析异常

    解析日期时 我的代码中不断出现异常错误 日期看起来像这样 Wed May 21 00 00 00 EDT 2008 这是尝试读取它的代码 DateTimeFormatter formatter DateTimeFormatter ofPat
  • 是否需要使用fetch_object或fetch_array?

    我最近发现我可以打印数据库中的结果而不使用mysqli fetch object功能 例如 假设我们有一个简单的 sql select 语句 可以使用如下所示的语句来执行 conn mysqli connect localhost root
  • 如何声明仅调试语句

    在 C 中 我可以使用以下代码来获得仅在调试构建期间执行的代码 我如何在 Xcode 中执行相同的操作 if DEBUG etc etc endif 您可以使用 ifdef DEBUG endif 你需要添加DEBUG 1到调试配置设置中项
  • 如何使用 FastAPI 在 HTMX 前端中使用 HX-Redirect?

    我试图在登录后在前端重定向 我像这样从我的 htmx 前端发出请求
  • 如何对 Google API 调用进行单元测试

    我有一个以下方法 它从 Google Analytics 检索访问次数最多的页面 public function getData limit 10 ids 12345 dateFrom 2011 01 01 dateTo date Y m
  • 删除绘图轴值

    我只是想知道是否有一种方法可以消除 r 图中的轴值 分别是 x 轴或 y 轴 我知道axes false将摆脱整个轴 但我只想摆脱编号 删除 x 轴或 y 轴上的编号 plot 1 10 xaxt n plot 1 10 yaxt n 如果
  • validation_epoch_end 与 DDP Pytorch Lightning

    你的问题是什么 我正在尝试实现一个需要访问整个数据的指标 因此 我尝试收集 epoch end 方法中的输出 而不是更新 step 方法中的指标 但是 输出仅包含每个设备获取的数据分区的输出 基本上 如果有 n 个设备 那么每个设备都会获得
  • SQL Server CE 不兼容的数据库版本

    我有一个 SQL Server CE 4 0 数据库 sdf文件 当我尝试从我的应用程序 WPF 对数据库进行查询时 出现以下错误 数据库版本不兼容 如果这是兼容文件 请运行修复 其他情况请参考文档 数据库版本 4000000 请求的版本
  • Phonegap - cordova 在 Android 和 iOS 设备上延迟且缓慢

    我刚刚开始使用 zend studio 开始我的第一个 PhoneGap 项目 但是 在我构建并部署它之后 该应用程序非常慢 Android 和 iOS 均可 滚动滞后 如果我按下按钮 转到下一页的速度很慢 有什么办法可以提高它的性能吗 提
  • 使用 Android 的 Mobile Vision API 扫描二维码

    我跟着这个tutorial http code tutsplus com tutorials reading qr codes using the mobile vision api cms 24680关于如何构建可以扫描二维码的 Andr
  • 获取运行云功能的运行时服务帐户

    有没有办法以编程方式从云功能获取运行时服务帐户的电子邮件 我知道我可以 猜测 默认的 App Engine 帐户 因为它始终是 appspot gserviceaccount com 但这不是我想要的 我本来期待有一些环境变量 https
  • ESLint 如何集成到 Create React App 中?

    当我跑步时npx create react app some name 为我创建了一个简单的 React 项目 当我随后窥视package json 似乎有一些 ESLint 存在的证据 因为有 eslintConfig extends r
  • Git 版本控制中忽略父目录

    如何忽略父目录 gitignore 我尝试了这种模式 但似乎它们不起作用 如果您想忽略某个文件夹但不想修改现有的 gitignore 请将 gitignore 放入仅包含星号的文件夹中 下面是一个快速的 BASH 示例 用于完成 idea
  • 无法在 Capistrano 3 的端口 80 上启动我的 Unicorn

    我在尝试运行时收到以下错误 帽子生产独角兽 开始 DEBUG 29ec5890 Command cd home ec2 user apps current RAILS ENV production BUNDLE GEMFILE home e
  • 如何编写完全可移植的 4 字节字符常量的编译时初始化

    遗留 代码大致如下所示 define MAKEID a b c d UInt32 a lt lt 24 UInt32 b lt lt 16 UInt32 c lt lt 8 UInt32 d define ID FORM MAKEID F