如何在C语言结构体中为无名字段命名?

7

让我们来考虑这个结构:

struct {
    int a;
    int _reserved_000_[2];
    int b;
    int _reserved_001_[12];
    int c;    
};

保留字段不应该被读取或写入。我的结构表示一个指向FPGA的描述符,其中有很多reserved字段。我最终用随机命名来命名它们,因为经过多年后,最初的升序编号已经没有任何意义了。

所以现在我有:

struct {
    int a;
    int _reserved_3hjdds1_[2];
    int b;
    int _reserved_40iuljk_[12];
    int c;    
};

如果只有空字段,会更加方便:

struct {
    int a;
    int;
    int b;
    int;
    int c;    
};

但它不起作用。

有什么其他替代方案可以避免为预留字段查找唯一名称?


1
编写一个代码生成器,用于生成结构声明。让它为保留成员创建顺序编号的名称。特别注意,如果保留成员的名称更改也没有关系,因为不应该有任何人访问这些成员。 - John Bollinger
你的意思是类似于 reserved_## __COUNTER__ 这样的吗? - nowox
既然保留字段不应该被使用,我不明白初始升序编号是否有意义,反正它只是用来使名称唯一而已。我会坚持使用第一个版本... - Dmitri
请注意,您也可以手动执行相应操作。因为再次强调,保留字段的名称并不重要,只要它们在每个结构类型中是不同的,您可以返回到编号字段,并根据需要执行手动重新编号。 - John Bollinger
我发现__COUNTER__存在一个角落问题。如果struct定义在一个*.h头文件中,并且各个*.c文件都包含它,那么__COUNTER__状态可能会因为在*.h包含之前如何使用__COUNTER__而有所不同。通过单独编译具有不同字段名称的struct是否能够正常工作或者会创建调试问题,我不确定。总之,这是一篇好文章。 - chux - Reinstate Monica
显示剩余3条评论
2个回答

5

通过一些宏魔法,应该可以实现您想要的目标:

#include <stdint.h>

#define CONCAT(x, y) x ## y
#define EXPAND(x, y) CONCAT(x, y)
#define RESERVED EXPAND(reserved, __LINE__)

struct
{
  uint32_t x;
  uint32_t RESERVED;
  uint16_t y;
  uint64_t RESERVED[10];
} s;

这将为您提供标识符,例如reserved11reserved13,但名称显然并不重要。

不错的尝试,但我仍然更喜欢我的答案,其中包含大写宏和关于__COUNTER__的警告。你还忘记了#include <stdint.h> - nowox
1
@nowox __LINE__ 是标准的 C 语言,而 __COUNTER__ 则不是。 - Lundin
1
请注意,如果您在同一行上有多个定义,则__LINE__将无法工作,但至少编译器会报错。我仍然认为这比使用__COUNTER__更好。 - nowox
2
@nowox 这是一个不错的特性,对吧?为什么要在同一行声明多个结构体成员? - Lundin

0
我知道,这个回答来得太晚了,但是你考虑过使用未命名的位域吗?
struct {
    int a;
    int : sizeof(int) * 8;
    int b;
    int : sizeof(int) * 8;
    int c;
};

这是ISO-C89标准,适用于我迄今遇到的所有C和C ++编译器,包括:gcc,g ++,clang,Borland C ++,甚至还包括旧的TurboC。


1
只有一个 int 的话是OK的,但OP需要两个和十二个 intint:sizeof(int)* 8 * 2int:sizeof(int)* 8 * 12; 会导致“error:‘<anonymous>’的宽度超过了其类型”的错误。 - chux - Reinstate Monica
你会得到这个错误,是因为你正在定义一个整数类型的位域。根据你的机器和系统,它通常是32位。所以你的整数位域的最大大小是int,我猜测是32位。因此,sizeof(int) * 8 * 2将给出一个64的结果。这是你定义的类型可能的两倍大小。 如果你需要超过1个int,只需添加尽可能多的行,每行写上int : sizeof(int) * 8;即可。 - Oliver Engelhardt
在源代码中使用12行而不是int _reserved_001_[12];会更糟糕,因为这会影响可读性和可维护性。更糟糕的是,这比常规变量名更加视觉上嘈杂,会分散注意力。这是一个有趣的想法,但对于问题提出的特定用例来说并不是很好。也许对于其他未来的读者可能会有用,特别是如果他们不需要比一个long longuintmax_t更宽的字段。 - Peter Cordes
这种技术被称为结构填充。但你完全是正确的。它不仅难看而且难以维护,而且甚至读写这些字段也很棘手。这远远不是干净的代码。 C语言没有提供私有或隐藏字段,每次尝试实现类似功能的都表明程序架构存在问题。但正如你所说,玩弄它是一个有趣的想法。 - Oliver Engelhardt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接