【问题标题】:Why is it valid to define a type as pointer to an undefined struct in C?为什么将类型定义为指向 C 中未定义结构的指针是有效的?
【发布时间】:2017-11-10 19:09:08
【问题描述】:

我正在研究第 3 方代码库,发现将类型声明为指向未定义结构的指针显然是有效的。作为一个最小的工作示例,考虑一个 C 文件 test.c,它只包含:

typedef struct foo *bar;

让我吃惊的是,这个文件使用命令编译没有任何问题

gcc test.c -shared

为什么编译器不会抱怨没有在任何地方声明 struct foo?

我的环境是 Ubuntu 16.04 和 gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609。

【问题讨论】:

  • 它不是“未定义的结构”,它是一个指向不完整类型的指针。

标签: c pointers struct


【解决方案1】:

上面的声明创建了一个struct foo前向声明。虽然你不能访问它的成员,但是你可以对指向它的指针进行操作。

这通常被称为不透明类型,用于向库的用户隐藏库的实现细节。

例如,一个库实现可能包含以下内容:

lib.c:

struct foo {
  int f1;
};

struct foo *init()
{
    return malloc(sizeof(struct foo));
}

void set1(struct foo *p, int val)
{
    p->f1 = val;
}

int get1(struct foo *p)
{
    return p->f1;
}

void cleanup(struct foo *p)
{
    free(p);
}

此库的头文件可能如下所示:

lib.h:

struct foo;

struct foo *init(void);
void set1(struct foo *p, int val);
int get1(struct foo *p);
void cleanup(struct foo *p);

该库的用户将使用init 函数来创建结构的实例,并使用set1get1 函数来读取/更新成员。但是,用户不能创建struct foo 的实例或访问成员,而无需通过其中一个接口函数。

【讨论】:

  • 但是是的,这是可能的,因为指向它的指针是相同的......这就是前向声明和所有这些的原因
  • 我想我真的会扭转局面,@coderredoc。所有指向结构类型的指针都具有相同大小的事实遵循,因为 C 允许声明不完整的结构类型(即带有标签但没有主体)并派生指向此类类型的指针。效果是结构指针的大小不能是结构成员的函数。
  • 啊,这似乎不是循环的。。@JohnBollinger:很多次我在这里读到相反的内容。我想没有有效的方法可以确定..这是什么驱动
  • 也许不是,@coderredoc,但如果我要尝试,我会指出标准实际上并不能保证结构指针的大小都相同。事实证明,这是一个普遍的实施决策。
  • ISO/IEC 9899:2011 §6.2.5 类型¶28:指向void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。类似地,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。所有指向结构类型的指针都应具有彼此相同的表示和对齐要求。所有指向联合类型的指针都应具有彼此相同的表示和对齐要求。指向其他类型的指针不需要具有相同的表示或对齐要求。
【解决方案2】:

因为指向结构的指针具有相同的大小(对于任何结构)。结构指针的大小不取决于它的定义。因为无论如何,指向它的指针的行为方式与任何其他结构指针相同。

【讨论】:

  • 我肯定遗漏了什么......如果我写“指针++”,当指针指向前向声明时,指针会增加多少?
  • 刚试了几种方法;编译器抱怨“错误:指向未知结构的指针的增量”和“错误:指向不完整类型的指针的算术”。
猜你喜欢
  • 2022-11-23
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 2010-10-05
  • 2018-07-05
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
相关资源
最近更新 更多