使用bool导出打包结构

Exporting Packed structures with bool

本文关键字:结构 包结构 bool 使用      更新时间:2023-10-16

导出包含布尔值的打包结构的最佳实践是什么?

我问这个问题是因为我试图找到最好的方法。当前I do:

#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类型,但感觉不对。

有更好的主意吗?

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

如果你希望更快,但可能会"浪费"几个字节的空间(即每个布尔标志一个值,参见sizeof bool讨论),你目前的方法是优越的。这是因为它可以直接加载和比较布尔值,而不必在打包字段中屏蔽它们(见下一节)。

如果你想节省空间,那么你应该看看C位域:

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值更密集的包装。

我认为,使用#pragma pack的痛苦(长期)大于收益(短期)。

  • 这是编译器特定的;

  • 我了解嵌入式系统或协议的场景。只需要一点点额外的努力,代码就可以被编写为无pragma的。

  • 我也想尽可能多地包装我的结构,并像您那样以更宽的优先方式布局成员。然而,我不介意损失2个字节,如果这允许我的代码符合标准和可移植的话。

我会做以下三件事:

  • 将标志声明为bool(您已经这样做了)并分配true/false
  • 把他们作为struct的最后成员(你已经这样做了)
  • 使用位域(根据其他堆栈者的建议)
结合

:

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

在c99之前的情况下,对typedef char bool;有风险。这会静默地破坏如下代码:

bool x = (foo & 0x100);

如果foo中设置了该位,则应该将x设置为真。enum也有同样的问题

在我的代码中,我实际上做typedef unsigned char bool;,但然后我小心地在表达式转换为bool的地方编写!!。这并不理想。

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