在C中应用可移植的位掩码和标志

奥希特里克

我使用各种微控制器架构/字长为嵌入式系统开发固件,并在可能的情况下尽量强调可移植性。我的问题是关于生成/应用安全且可移植的位掩码和标志,对于任何非通用代码,情况如何?

位掩码

#define MASK_8_V1(x) ((x) & 0xFF)
#define MASK_8_V2(x) ((x) & 0x00FF)

a = MASK_8_V1(b)
a = MASK_8_V2(b)

是否总是保证除b的低8位外所有位都为零的a的宽度值?这两个版本之间有什么区别,因为如果有必要对它们进行签名扩展?

标志

#define GEN_FLAG_16(x) ((0xFFFF) & ((unsigned) 1 << (x)))
#define GEN_FLAG_32(x) ((0xFFFFFFFF) & ((unsigned long) 1 << (x)))

如果我需要一个通用宏来生成标志常量,是否会始终为列出的宽度生成一个标志常量?

两个都

#define CHECK_FLAG_16(x, y) ((x) & GEN_FLAG_16(y))
#define CHECK_FLAG_32(x, y) ((x) & GEN_FLAG_32(y))

if(CHECK_FLAG_16(a, b))
{
    // Do something.
}

结合前面的场景,如果设置了b的原始值中的所需位,它将始终执行内部代码吗?

对于所有情况,假定:

  • 符合C90或C99的编译器
  • a和b可以是带符号或无符号的本机C类型的任意组合
  • x始终计算为正整数类型
  • 任意本机字长

编辑那些提到的用法stdint.h:最近我遇到一个问题,我们需要将我已经写过的串行协议处理程序移植到另一个微控制器系列中,只是发现RAM不可字节寻址。我们最终删除了uint8_t的所有使用,并进行了修改以使用16位可寻址内存。这让我想知道是否可以使用本机C类型以不同的方式实现它,以避免以后进行修改。我的问题间接地来自那个问题。

伦丁

是否总是保证除b的低8位外所有位都为零的a的宽度值?

是的。

但是,最终的宏类型可能会有所不同,具体取决于类型b这可能会导致可移植性问题。因此,最好将结果转换为预期的类型,例如uint32_t

两个版本之间有什么区别

不,它们是等效的。

如有必要,应延长签收时间

在带符号类型上使用按位运算符通常没有任何意义。

如果我需要一个通用宏来生成标志常量,是否会始终为列出的宽度生成一个标志常量?

是的,但是结果将根据int或long的大小而具有不同的类型。

我最近遇到一个问题,我们需要将我已经写过的串行协议处理程序移植到另一个微控制器系列中,只是发现RAM不可字节寻址。

那主要是编译器的问题。同样,还不清楚uint8_t在这样的系统上怎么会出现问题,总是存在隐式整数提升。听起来好像您遇到了一些算法问题,也许是使用uint8_t*指针的代码或类似的代码


从脚步来看,完全可移植的代码如下所示:

#define MASK8_32(x) ((uint32_t)(x) & 0xFFul)

#define GEN_FLAG_16(x) (uint16_t)( 0xFFFFu & (1u << (x)) )
#define GEN_FLAG_32(x) (uint32_t)( 0xFFFFFFFFu & (1ul << (x)) )

现在,大多数潜在的int大小和隐式类型提升依赖关系已被删除。


这里主要的可移植性问题是:

  • 你的代码依赖于规模intlong这样的代码是不可移植的,因为这些类型可具有任何尺寸。使用stdint.h中的固定宽度整数类型解决许多此类问题。
  • 您的代码没有意识到默认类型和整数文字的带符号性。在许多情况下,对有符号的操作数使用按位运算符,这总是一个坏主意。
  • 您似乎通常并不了解隐式类型提升在C中的工作方式。

事实证明,所有这些问题都可以通过MISRA-C解决我建议购买MISRA-C:2012并阅读以用于教育目的。


作为边注,如代码a = OBSUCRE_MACRO(b);少得多可读不是像代码a = b & 0xFF;因为您始终可以假设读者是C程序员,因此知道C语言,但不知道您的私有秘密宏语言。

此外,类似函数的宏是不安全的,应尽可能避免使用。

因此,我首先质疑这些宏有什么用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么将标志与位掩码和标志的按位 AND 的结果进行比较?

来自分类Dev

无法应用位掩码

来自分类Dev

在下面的示例中读取位掩码和位

来自分类Dev

在C ++中获取类型的基础位的通用且可移植的方法是什么?

来自分类Dev

位掩码和长久

来自分类Dev

位掩码枚举的通用单标志枚举

来自分类Dev

是否可以在可移植项目(Android和iOS)中应用“材料设计”?

来自分类Dev

是否有C ++位域的可移植替代品

来自分类Dev

枚举值中包含的位掩码标志的最佳方法是什么?

来自分类Dev

C语言中的按位运算和掩码

来自分类Dev

GLib类型的位大小和可移植到更多奇特(例如16位字符)平台的可移植性

来自分类Dev

通过C#中的位掩码存储多个值

来自分类Dev

C#可移植应用程序与.NET

来自分类Dev

Powershell中的位掩码转换

来自分类Dev

在Swift中检查位掩码

来自分类Dev

C和C ++ .lib文件可移植吗?

来自分类Dev

C和C ++ .lib文件可移植吗?

来自分类Dev

测试位掩码是否只有一个标志

来自分类Dev

C系统编程clone()标志位的值和操作

来自分类Dev

使用C#可移植库中的F#可移植类库

来自分类Dev

在处理字符串和短裤时更快地应用位掩码的方法?

来自分类Dev

将位掩码应用于BufferedImage

来自分类Dev

c / c ++中endian的最佳且可移植的转换

来自分类Dev

位串和标志移位

来自分类Dev

GLib类型的位大小和可移植到更多奇特(例如16位字符)平台的能力

来自分类Dev

如何在Common Lisp中移植命令行参数和标志?

来自分类Dev

为什么有人会在C语言中按位与8位值和16位掩码进行比较?

来自分类Dev

使用位掩码将应用程序启用的功能存储到数据库中

来自分类Dev

如何在c ++ STL文件读取过程中可移植地捕获和处理UTF“ EN DASH”弊端?

Related 相关文章

  1. 1

    为什么将标志与位掩码和标志的按位 AND 的结果进行比较?

  2. 2

    无法应用位掩码

  3. 3

    在下面的示例中读取位掩码和位

  4. 4

    在C ++中获取类型的基础位的通用且可移植的方法是什么?

  5. 5

    位掩码和长久

  6. 6

    位掩码枚举的通用单标志枚举

  7. 7

    是否可以在可移植项目(Android和iOS)中应用“材料设计”?

  8. 8

    是否有C ++位域的可移植替代品

  9. 9

    枚举值中包含的位掩码标志的最佳方法是什么?

  10. 10

    C语言中的按位运算和掩码

  11. 11

    GLib类型的位大小和可移植到更多奇特(例如16位字符)平台的可移植性

  12. 12

    通过C#中的位掩码存储多个值

  13. 13

    C#可移植应用程序与.NET

  14. 14

    Powershell中的位掩码转换

  15. 15

    在Swift中检查位掩码

  16. 16

    C和C ++ .lib文件可移植吗?

  17. 17

    C和C ++ .lib文件可移植吗?

  18. 18

    测试位掩码是否只有一个标志

  19. 19

    C系统编程clone()标志位的值和操作

  20. 20

    使用C#可移植库中的F#可移植类库

  21. 21

    在处理字符串和短裤时更快地应用位掩码的方法?

  22. 22

    将位掩码应用于BufferedImage

  23. 23

    c / c ++中endian的最佳且可移植的转换

  24. 24

    位串和标志移位

  25. 25

    GLib类型的位大小和可移植到更多奇特(例如16位字符)平台的能力

  26. 26

    如何在Common Lisp中移植命令行参数和标志?

  27. 27

    为什么有人会在C语言中按位与8位值和16位掩码进行比较?

  28. 28

    使用位掩码将应用程序启用的功能存储到数据库中

  29. 29

    如何在c ++ STL文件读取过程中可移植地捕获和处理UTF“ EN DASH”弊端?

热门标签

归档