在结构中强制枚举字段的大小 [英] Forcing the size of an enum'd field in a structure

查看:153
本文介绍了在结构中强制枚举字段的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[注意:这与在C中指定枚举类型的大小 C中枚举的大小是多少?,但在这些问题中,问题是如何最小化封闭结构的大小。在这里,我们要指定结构体的各个成员的大小,但仍然可以获得typedef'枚举的文档优势]



我是实现串行通信协议的客户端。我想使用C结构来捕获串行数据包的格式,我想使用C枚出来定义数据包中各种插槽的合法值。


$ b $我没有看到这样做,但是由于我使用GCC,可能是可能的。



作为一个假设的问题示例假设我收到的数据包看起来像这样:

  typedef struct {
uint16_t appliance_type;
uint8_t电压;
uint16_t crc;
} __attribute __((__ packed__))appliance_t;

很清楚,我很确定我会得到一个五个字节长的结构。但是它并没有捕捉到 appliance_type 电压只能承担某些值的事实。



我喜欢这样的东西...

  typedef枚举{
kRefrigerator = 600,
kToaster = 700,
kBlender = 800
} appliance_type_t;

typedef枚举{
k120vac = 0,
k240vac = 1,
k12vdc = 2
} voltage_t;

typedef struct {
appliance_type_t appliance_type;
voltage_t电压;
uint16_t crc;
} appliance_t;

...但是我知道没有办法指定appliance_type_t是16位,而voltage_t是8位。



有没有办法让我的蛋糕吃东西?



更新: h3>

我需要明确指出,我并不期望编译器强制枚举值作为各个字段的设置器!相反,我发现typedef的枚举是代码维护者的一个有用的构造,因为它明确了预期的值。



注意:我研究了这个,我注意到GCC枚举接受 __属性__ 规范,但我不确定有帮助。

解决方案

我建议您将原始数据与抽象分开。例如:

  typedef struct {
uint16_t type;
uint8_t电压;
uint16_t crc;
} __attribute __((__ packed__))raw_data_t;

typedef struct {
appliance_type_t type;
voltage_t电压;
uint16_t crc;
} appliance_t;

inline appliance_t raw_data_to_appliance(const raw_data_t * raw)
{
appliance_t app =
{
.type =(appliance_type_t)raw-> type,
.voltage =(voltage_t)raw-> voltage,
.crc = raw-> crc,
};
return app;
}

这不应该产生很多开销代码。另请参阅如何创建类型安全枚举?


[NOTE: this is related to Specifying size of enum type in C and What is the size of an enum in C?, but in those questions, the issue was how to minimize the size of the enclosing struct. Here, we want to specify the size of the individual members of the struct, but still get the documentation advantage of typedef'd enums]

I'm implementing the client side of a serial communication protocol. I'd like to use C structs to capture the format of a serial packet, and I'd like to use C enums to define the legal values of the various slots in the packet.

I don't see a way to do both, but since I'm using GCC, it may be possible.

As a hypothetical example of the problem, assume the packet I receive looks like this:

typedef struct {
  uint16_t appliance_type;
  uint8_t voltage;
  uint16_t crc;
} __attribute__((__packed__)) appliance_t;

That's pretty clear, and I'm pretty sure I'll get a struct that is five bytes long. But it doesn't capture the fact that appliance_type and voltage can only take on certain values.

I'd prefer something like this...

typedef enum {
  kRefrigerator = 600,
  kToaster = 700,
  kBlender = 800
} appliance_type_t;

typedef enum {
  k120vac = 0,
  k240vac = 1,
  k12vdc = 2
} voltage_t;

typedef struct {
  appliance_type_t appliance_type;
  voltage_t voltage;
  uint16_t crc;
} appliance_t;

...but there's no way that I know of to specify that appliance_type_t is 16 bits and voltage_t is 8 bits.

Is there a way to have my cake and eat it too?

update:

I need to make it clear that I'm NOT expecting the compiler to enforce the enum'd values as setters for the respective fields! Rather, I find that typedef'd enums are a useful construct for maintainers of the code, since it makes explicit what the intended values are.

Note: As I researched this, I noticed that GCC enums accept __attribute__ specifications, but I'm not sure that helps.

解决方案

I would suggest that you keep the "raw data" separate from the abstraction. For example:

typedef struct {
  uint16_t type;
  uint8_t  voltage;
  uint16_t crc;
} __attribute__((__packed__)) raw_data_t;

typedef struct {
  appliance_type_t type;
  voltage_t voltage;
  uint16_t crc;
} appliance_t;

inline appliance_t raw_data_to_appliance (const raw_data_t* raw)
{
  appliance_t app =
  {
    .type    = (appliance_type_t)raw->type,
    .voltage = (voltage_t)raw->voltage,
    .crc     = raw->crc,
  };
  return app;
}

This shouldn't yield much overhead code. See also How to create type safe enums?

这篇关于在结构中强制枚举字段的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆