【问题标题】:A pointer to array of forward declared structures in C指向 C 中前向声明结构数组的指针
【发布时间】:2020-04-30 14:33:26
【问题描述】:

我对 C 中的前向声明有疑问。

代码

typedef struct yhash_s t_yhash;// forward declaration
struct yhash_s {
    size_t  size_h; 
    t_yhash (*yhash)[];// pointer to array of structures
};

使用 gcc 编译代码后,它会报错:

错误:数组类型有不完整的元素类型‘t_yhash’ {aka ‘struct yhash_s’}

我确实知道t_yhash(尚不知道)并且无法计算数组的大小,但我询问的是指向一个未知大小的数组的指针,恕我直言,这应该是完全可以解决的。

如何修复该前向声明和结构本身?

【问题讨论】:

  • 是你的括号导致了问题。你实际上的意思是t_yhash **yhash;
  • 如果你有一个数组,你需要知道数组中每个元素的大小。你不能有一个未知大小的结构数组,也不能声明指向它的指针,因为你不知道它指向的大小。
  • @KamilCuk 你实际上可以ideone.com/3FKCrJ
  • @EugeneSh。您的示例使用 int 作为函数数组的返回类型,因此它可以工作。但这不是 OP 的意图,int 也具有已知类型,因此即使 OP 的意图也不适用。
  • @AhmedMasud 我的回复完全是对 KamilCuks 的评论(现已删除..)。

标签: c gcc


【解决方案1】:

回复您帖子的这一部分:

如何修复前向声明和结构本身?

您可以使用void * 来存储您的数组,然后再将其转换回来。

typedef struct yhash_s t_yhash;
struct yhash_s {
               size_t  size_h;
               void *yhash;
               };

static inline t_yhash (*yhash(t_yhash y))[] {
    return y.yhash;
}

如果函数语法太钝:

typedef t_yhash t_yhash_array[];

static inline t_yhash_array *yhash(t_yhash y) {
    return y.yhash;
}

例如:

t_yhash x[10];
t_yhash y = { 10, &x };
assert(yhash(y) == &x);

【讨论】:

  • 谢谢@jxh,这太疯狂了——我花了 5 分钟来阅读你的代码,哈哈! :)
  • 好的,我给出了等效的函数,带有 typedef 来说明它的含义。
【解决方案2】:

问题在于数组声明符可能没有不完整的类型作为元素类型(C11 6.7.6.2/1)。而t_yash(即struct yhash_s)直到结构定义的右大括号才完成。

这条规则还负责另一条琐事;拥有(在结构定义完成之前)是合法的:

void func( t_yhash *a );

但不合法拥有:

void func( t_yhash a[] );

即使调整规则在不完整元素类型规则的情况下也能正常工作。

通过改进此规则以允许函数原型等某些情况,可能可以稍微改进语言设计,但这显然不是语言设计委员会提出的。

但即使没有这条规则,您的用例也可能会遇到另一个问题;指针的大小可能未知。 “指向结构 X 的数组的指针”与“指向结构 Y 的数组的指针”具有不同的大小是合法的(尽管在实践中不太可能)。有一个规则是所有指向 struct 的指针必须具有相同的大小,但对于指向数组的指针则没有这样的规则。

【讨论】:

  • 指向不完整类型的指针是不完整类型吗? (虽然不是说它在这里相关)
  • C 2018 6.2.5 1 说“在翻译单元内的不同点,对象类型可能不完整(缺乏足够的信息来确定该类型对象的大小)或完整(有足够的信息) 。”所以,如果你知道它有多大,它似乎是完整的。
  • @EugeneSh。我不这么认为——否则void f (struct x *p) {} 将是一个错误(C11 6.7.6.3/4)。但这是一个有趣的问题
  • 是一个完整的类型。特别是对于结构指针,它们应该具有相同的表示。
  • @M.M:对于struct x *p,我们知道p 有多大,因为所有结构指针都具有相同的大小。对于int (*p)[],实现可以为不同的数组使用不同大小的指针,所以我们可能不知道p 有多大。
猜你喜欢
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多