我应该使用位字段来映射传入的串行数据吗?

2024-04-04

我们有通过串行(蓝牙)传入的数据,它映射到特定的结构。该结构的某些部分是子字节大小,因此“显而易见”的解决方案是将传入数据映射到位字段。我无法确定的是机器或编译器的位字节顺序是否会影响它(这很难测试),以及我是否应该完全放弃位字段。

例如,我们有一条1.5字节的数据,所以我们使用结构体:

{
    uint8_t data1; // lsb
    uint8_t data2:4; // msb
    uint8_t reserved:4;
} Data;

保留位始终为 1

例如,如果传入的数据是 0xD2,0xF4,则值为 0x04D2,即 1234。

我们使用的结构始终适用于我们测试过的系统,但我们需要它尽可能可移植。

我的问题是:

  • Will data1无论字节序如何,始终按预期表示正确的值(我假设是,并且硬件/软件接口应始终正确处理单个整个字节 - 如果发送 0xD2,则应接收 0xD2)?

  • Could data2 and reserved是错误的方式,与data2代表高4位而不是低4位?

If yes:

  • 位字节顺序(通常)是否取决于字节字节顺序,或者它们可以完全不同吗?

  • 位字节顺序是由硬件还是编译器决定的?看起来 Intel 上的所有 Linux 系统都是一样的——对于 ARM 来说也是如此吗? (如果我们可以说我们可以支持所有 Intel 和 ARM linux 版本,那应该没问题)

  • 是否有一种简单的方法可以在编译器中确定它的方式,并在需要时保留位字段条目?

虽然位字段是映射传入数据的最简洁的代码方式,但我想我只是想知道放弃它们并使用类似的东西是否更安全:

struct {
    uint8_t data1; // lsb (0xFF)
    uint8_t data2; // msb (0x0F) & reserved (0xF0)
} Data;

Data d;

int value = (d.data2 & 0x0F) << 16 + d.data1

我们之所以不这样做,首先是因为许多数据字段小于 1 个字节,而不是超过 1 个字节 - 这意味着通常对于位字段,我们不必进行任何屏蔽,并且移动,因此后处理更简单。


我应该使用位字段来映射传入的串行数据吗?

不会。位域有很多实现指定的行为,这使得使用它们成为一场噩梦。

无论字节序如何,data1 是否始终按预期表示正确的值。

是的,但那是因为uint8_t是最小的可能寻址单元:字节。对于较大的数据类型,您需要注意字节顺序。

难道data2和reserved是错误的方式,data2代表高4位而不是低4位?

是的。它们也可以位于不同的字节上。另外,编译器不必支持uint8_t对于位域,即使它会支持该类型。

位字节顺序(通常)是否取决于字节字节顺序,或者它们可以完全不同吗?

最低有效位总是在最低有效字节中,但在 C 中无法确定where该位将在字节中。

位移运算符提供了足够好的顺序的可靠抽象:对于数据类型uint8_t the (1u << 0)总是最不重要的并且(1u << 7)对于所有编译器和所有体系结构来说,最重要的位。

另一方面,位字段的定义非常糟糕,以至于您无法通过定义字段的顺序来确定位的顺序。

位字节顺序是由硬件还是编译器决定的?

编译器决定数据类型如何映射到实际位,但硬件对其影响很大。对于位字段,同一硬件的两个不同编译器可以按不同的顺序放置字段。

是否有一种简单的方法可以在编译器中确定它的方式,并在需要时保留位字段条目?

并不真地。如果可能的话,这取决于您的编译器如何执行此操作。

虽然位字段是映射传入数据的最简洁的代码方式,但我想我只是想知道放弃它们并使用类似的东西是否更安全:

绝对放弃位字段,但我也建议为此目的完全放弃结构,因为:

  • 您需要使用编译器扩展或手动工作来处理字节顺序。

  • 您需要使用编译器扩展来禁用填充,以避免由于对齐限制而出现间隙。这会影响某些系统上的成员访问性能。

  • 您不能有可变宽度或可选字段。

  • 如果您不知道这些问题,很容易出现严格的别名违规。如果为数据帧定义字节数组并将其转换为指向结构的指针,然后取消引用它,那么在很多情况下都会遇到问题。

相反,我建议手动执行此操作。定义字节数组,然后在必要时使用位移位和掩码将每个字段分开,手动将每个字段写入其中。您可以为基本数据类型编写简单的可重用转换函数。

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

我应该使用位字段来映射传入的串行数据吗? 的相关文章

随机推荐

  • Python 有与 java.lang.Math.nextUp 等效的东西吗? [复制]

    这个问题在这里已经有答案了 我有一个Pythonfloat 我想要floats 为 1ULP http en wikipedia org wiki Unit in the last place更大和更小 在Java中 我会这样做Math n
  • 在 CSS 中指定打印的细线粗细

    如果我有一个打印 CSS 样式元素 border 1px solid black or border 0 25pt solid black 打印时线条很粗 至少 1 磅 如果我尝试更小的值 例如 0 05pt 则该线根本不会出现 我怎样才能
  • 同名的变量和常量

    我有一个C代码片段如下 const int x 5 void main int x x int y sizeof x sizeof int printf d y 代码片段将被编译并正确运行 但我不明白如何区分 x variable 和 x
  • 什么是 git-cache 以及 git-cache 中存储了什么

    事实上 我读了很多关于 git 的东西 我知道我可以通过删除缓存git rm cached 命令但我无法理解这个概念git 缓存 什么是缓存 而GIT中的缓存位置又在哪里呢 该缓存是存储在 RAM 中还是文件中 git 中使用缓存来提高性能
  • Android Studio 中的多个本机模块

    我有一个当前在 Visual Studio 中设置的 C 代码库 在 Windows 上运行 其中包含多个具有相互依赖关系的项目 我正在尝试将其转移到 Android Studio 以使其在 Android 上运行 我熟悉 Visual S
  • Facebook Unity SDK,如何强制使用webview而不是FB App登录

    默认情况下 如果用户安装了 FB Unity SDK 它将尝试使用 FB App 进行登录 否则 它将回退到使用基于 HTML 的弹出窗口来让用户登录 然而 FB 应用程序仅适用于 API 1 0 basic info 权限 将因 publ
  • 第 8 章 Rails 教程记住令牌错误

    本章介绍添加记住令牌 以确保记住用户登录状态 并且仅当用户明确注销时才清除会话 我了解在我的应用程序中拥有此功能的重要性 因此希望确保它正常工作 但是 当我运行时 我遇到了很多错误 bundle exec rspec spec 我怀疑它们与
  • 从 SQL 表中的行中删除尾随“:”字符

    我有数百万行的表 每行都有一个 nvarchar max 列 当我填充数据库时 我忘记删除结尾的 字符 遍历每一行并删除最后一个字符的最快 最有效的方法是什么 我认为必须有一种比使用看起来昂贵的 REPLACE 更快的方法来做到这一点 这是
  • 我们可以在 Android 中的短信到达收件箱之前将其删除吗?

    我正在从收件箱中删除一条短信 但我想知道 如何在它到达收件箱之前将其删除 Yes 尽管对这个问题有一些负面反应 但短信拦截有合法的用途 例如 自动电话号码验证 通过短信提供的服务 尽管通常这应该通过数据短信来完成 或者通过处理特殊格式的消息
  • Hexfloat机械手和精度

    如何使用输出hexfloat操纵器忽略任何精度ostream include
  • 如何在 Windows 中从 Google Code 下载/签出项目?

    当没有准备好的可用下载时 如何从 Google Code 下载整个项目的 ZIP 文件 这是我在结帐页面上看到的 命令行访问使用此命令可以匿名查看最新的项目源码 svn checkout http myproject googlecode
  • 向将数组作为字段之一的 Hive 表插入行时出现错误 10293

    我使用以下查询创建了一个配置单元表 create table arraytbl id string model string cost int colors array
  • ASP.NET 版本列表?

    感谢 stackoverflow 上的问答 我刚刚发现如何确定托管提供商服务器上安装的版本 现在我需要知道这个数字意味着什么 Using 在我的本地计算机上返回 2 0 50727 3053 有人能给我一份实际版本 1 1 1 2 等的列表
  • Maven多模块和Spring微服务的区别?

    我正在阅读下一个项目的 Spring 微服务 Tut 说 这种架构风格将主应用程序划分为一组称为微服务的子应用程序 一个大型应用程序划分为多个协作进程 所以我们已经有了一个框架 Maven 多模块 根据我的经验 我将项目分开了 尽管确实如此
  • 编译器无法推断返回类型

    Swift 无法推断函数的返回类型 该函数的参数是闭包 并且返回类型是从闭包的返回类型推导出来的 给定这个通用类 class Bar
  • ScikitLearn 的 MLPClasssifier 在输出层使用什么样的激活?

    我目前正在处理给定类标签 0 和 1 的分类任务 为此 我使用 ScikitLearnMLPClassifier为每个训练示例提供 0 或 1 的输出 但是 我找不到任何文档 说明 MLPClassifier 的输出层到底在做什么 哪个激活
  • IE10支持FormData()吗?

    我读了 here http msdn microsoft com en us library ie hh772723 v vs 85 aspx IE10 支持 FormData 但是当我在 IE10 JavaScript 控制台中输入以下内
  • 在服务器上运行我的 Rails 应用程序

    这是我第一次将 Rails 应用程序部署到服务器 它在本地运行得很好 但是当我尝试将其移动到服务器进行生产时 它没有显示 我得到的只是显示我的项目文件夹的图像 我需要做任何改变吗 以下是我已经完成的更改 数据库 yml gt 生产 改变了环
  • php imagecopyresized vs imagecopyresampled vs imagecopy 优点/缺点

    这些似乎都在做同样的事情 各自的优点 缺点是什么 imagecopyresized vs imagecopyresampled vs imagecopy 我正在调整用户提交的图像的大小 所以我有一个使用 newImage imagecrea
  • 我应该使用位字段来映射传入的串行数据吗?

    我们有通过串行 蓝牙 传入的数据 它映射到特定的结构 该结构的某些部分是子字节大小 因此 显而易见 的解决方案是将传入数据映射到位字段 我无法确定的是机器或编译器的位字节顺序是否会影响它 这很难测试 以及我是否应该完全放弃位字段 例如 我们