C’替换’具有灵活阵列成员的结构

考虑以下C99结构,以灵活的数组成员结束:

struct hdr
{
  size_t len;   
  size_t free;  
  char buf[];
};

例如,len使用内联函数(将被放入头文件)访问,像这样,将buf作为其参数:

static inline size_t slen(const char *s)
{
  struct hdr *h = (struct hdr*)(s - (int)offsetof(struct hdr, buf));
  return h->len;
}

这是库的一部分,用C编译器编译.但是,我想从C访问这个库;这实际上意味着相应的头文件(具有适当的extern“C”{…} guard)必须是有效的C代码.一种可能的解决方案是在源代码体中定义slen函数,完全避免内联代码,但这不是最优的.

我的想法是定义一个有效的虚拟C结构,并且我可以某种方式映射到hdr,例如

struct cpp_hdr
{
  size_t len;
  size_t free;
  char buf[1];
}

请注意,我只想获得len和free的正确(负)偏移值;不打算访问buf.

现在我的问题是:有任何保证

static inline size_t slen(const char *s)
{
  struct cpp_hdr *h = (struct cpp_hdr*)(s - (int)offsetof(struct cpp_hdr, buf));
  return h->len;
}

工作,给出相同的结果?

最佳答案
在形式上没有任何保证,因为C不支持灵活的数组:没有这样的东西,没有这样的语法.

在实践中,编译器不会直接做任何事情.所以不会引入任何不知名的填充.然而,为了使这一点非常清楚,我将使用例如数组大小. 666而不是1,它在更一般的情况下工作得更好(例如,1个字符的小数组可能被移动到某些其他结构中的某个填充区域中).作为一个好处,聪明的分配代码将不再简单.所以必须正确完成.

所有这些说,它确实听起来像一个16位Windows BSTR,除了BSTR在长度和字符串数据之间没有这个差距.考虑这个图书馆是否只是一个人没有理由重新发明轮子.如果是这样,我建议改用原车轮.

转载注明原文:C’替换’具有灵活阵列成员的结构 - 代码日志