【问题标题】:Exporting Packed structures with bool使用 bool 导出打包结构
【发布时间】:2014-05-01 04:23:33
【问题描述】:

导出包含布尔值的压缩结构的最佳做法是什么?

我问这个是因为我试图找到最好的方法来做到这一点。目前我做的:

#ifndef __cplusplus
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>    //size is 1.
#else
typedef enum {false, true} bool; //sizeof(int)
#endif
#endif

现在在上面,布尔值的大小可以是 1 或 sizeof(int)..

所以在这样的结构中:

#pragma pack(push, 1)
typedef struct
{
    long unsigned int sock;
    const char* address;
    bool connected;
    bool blockmode;
} Sock;
#pragma pack(pop)

如果使用 C 与 C99 和 C++ 相比,对齐方式是不同的。如果我将其导出为整数,那么布尔值为 1 的语言会出现对齐问题,需要填充结构。

我想知道在 C99 之前的情况下是否最好将 bool 类型定义为 char,但感觉不对。

有更好的想法吗?

【问题讨论】:

  • 在 int 字段中使用位标志怎么样?
  • 大小不会还是sizeof(int)吗?你能详细说明一下吗?
  • 这个想法是在任何底层整数字段(int、short、char 等)中使用 2 位标志而不是 2 布尔值。
  • 突然间我们得到了这个答案。
  • 我建议使用stdint.h(参见here)来明确和可靠地确定数据类型的大小。这将使处理打包结构的对齐变得更容易。

标签: c++ c c99


【解决方案1】:

这取决于您在寻找什么:保留空间但运行一些额外的指令,或者浪费一些字节但运行得更快。

如果您希望速度快,但可能“浪费”几个字节的空间(即每个布尔标志的单个值,请参阅sizeof bool 讨论),您当前的方法是优越的。这是因为它可以直接加载和比较布尔值,而无需将它们从打包字段中屏蔽掉(见下)。

如果您想节省空间,那么您应该查看C bitfields

struct Sock {
    ...
    int connected:1; // For 2 flags, you could also use char here.
    int blockmode:1;
}

或滚动您自己的“标志”并将位设置为整数值:

#define SOCKFLAGS_NONE      0
#define SOCKFLAGS_CONNECTED (1<<0)
#define SOCKFLAGS_BLOCKMODE (1<<1)

struct Sock {
    ...
    int flags; // For 2 flags, you could also use char here.
}

这两个示例都产生了或多或少相同的代码,这些代码会屏蔽位和移动值(额外指令),但比简单的bool 值更密集。

【讨论】:

    【解决方案2】:

    恕我直言,使用#pragma pack 带来的痛苦(长期)多于收获(短期)。

    • 它是特定于编译器的;非标准且不可移植

    • 我了解嵌入式系统或协议方案。只需一点额外的努力,就可以免费编写代码。

    • 我也想尽可能地打包我的结构,并像您一样以更广泛的优先方式布置成员。但是,我不介意丢失 2 个字节,如果这样可以让我的代码符合标准且可移植。

    我会做以下三件事:

    • 将标志声明为bool(您已经这样做了)并分配true/false
    • 将它们作为struct 的最后一个成员(您已经这样做了)
    • 使用位域(根据堆栈器的建议)

    结合这些:

    typedef struct Sock
    {
        long unsigned int sock;
        const char* address;
        bool connected : 1;
        bool blockmode : 1;
    } Sock;
    

    【讨论】:

    • 问题是bool connected: 1;是一个gcc扩展。它不允许您指定位域的type
    • @Braondon:在我的理解和测试中,bool connected : 1 符合标准。它与-std=XXX -pedantic 编译为XXX = c99, c++98, c++0x
    【解决方案3】:

    在 C99 之前的情况下,typedef char bool; 是有风险的。这将默默地破坏代码,例如:

    bool x = (foo & 0x100);
    

    如果在foo 中设置了该位,则应该将x 设置为true。枚举也有同样的问题。

    在我的代码中,我实际上是在使用typedef unsigned char bool;,但是我会小心地在任何将表达式转换为bool 的地方写上!!。这并不理想。

    根据我的经验,与在 C90 的结构或位域中使用 bool 相比,在整数类型中使用标志会导致更少的问题。

    【讨论】:

      猜你喜欢
      • 2021-05-29
      • 1970-01-01
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2015-04-13
      • 2010-12-21
      相关资源
      最近更新 更多