【问题标题】:Are identical anonymous structures compatible?相同的匿名结构是否兼容?
【发布时间】:2021-06-23 16:29:35
【问题描述】:

考虑这段代码sn-p:

#include <threads.h>

int thread_start(void *ptr)
{
    struct {
        int a;
        int b;
    } *data = ptr;

    return 0;
}

int main(int argc, char *argv[])
{
    struct {
        int a;
        int b;
    } data;

    thrd_t thread;
    thrd_create(&thread, thread_start, &data);
    thrd_join(thread, NULL);
    return 0;
}

关于 void *struct { int; int } * 的转换,假设匿名结构的字段与最初分配的结构的字段相同,这是根据 C 标准明确定义的行为吗?

【问题讨论】:

  • 我想是这样,但在标准中找不到明确的参考。不过,其他人可能比我做得更好。
  • 这能回答你的问题吗? Compatible types and structures in C 好像不是。
  • @EugeneSh。我认为这表明它们不是直接分配的兼容条款。但是,via void* 的投射和重新投射有点不同。毕竟,它们都必须具有相同的别名/对齐要求等。
  • 我记得在某处读到过,两个结构是等价的,当且仅当它们逐个字符完全相同时。不记得它是否仅适用于标记结构或所有(包括匿名)结构。

标签: c language-lawyer standards


【解决方案1】:

如果这些结构不在同一个文件中,它们将是兼容的。

如果 thread_start 在单独编译的 .c 文件中定义(即单独的翻译单元),那么它们将是兼容的。具体来说,成员的名称、类型和顺序是相同的,并且它们都具有相同的标签,在这种情况下是无标签。

C standard§6.2.7 ¶1 部分列出了这些要求:

如果它们的类型相同,则两种类型具有兼容类型。 确定是否有两种类型的附加规则 compatible 在 6.7.2 中对类型说明符进行了描述,在 6.7.3 用于类型限定符,6.7.6 用于声明符。 此外,在中声明了两种结构、联合或枚举类型 单独的翻译单元如果它们的标签和 成员满足以下要求:如果已声明 一个标签,另一个应该用相同的标签声明。 如果两者都在各自的任何地方完成 翻译单元,则适用以下附加要求: 他们之间应该存在一一对应的关系 成员,使得每对对应的成员是 用兼容的类型声明;如果声明了该对中的一个成员 使用对齐说明符,另一个声明为 等效对齐说明符;如果这对中的一个成员 用一个名字声明,另一个用相同的名字声明 name. 对于两个结构,对应的成员应在 相同的顺序。对于两个结构或联合,对应 位域应具有相同的宽度。对于两个枚举, 相应的成员应具有相同的值。

因此,如果这些结构不在同一个文件中,兼容。但是因为它们是,结构是不兼容的。

§6.7.2.1 ¶8 说:

struct-or-union-specifier 中的 struct-declaration-list 的存在声明了翻译单元内的新类型。

因此,第 6.7.2.1 节指定了在单个翻译单元中发生的情况。当声明位于单独的翻译单元中时,第 6.2.7 节中的规范会覆盖第 6.7.2.1 节中的规范。

注意:6.2.7 和 6.7.2 很容易混淆。

【讨论】:

  • 在您所引用的内容中,它是否明确排除了在同一翻译单元中定义的结构?有人可能会争辩说,提到“独立”单元只是为了清楚地说明相同的单元。
  • @AdrianMole 如果不区分两种情况,“在单独的翻译单元中声明”部分难道不是完全多余的吗?
  • 这就引出了一个问题,如果在翻译单元“a”中定义了两个相同的匿名结构类型,在翻译单元“b”中定义了另一个相同的匿名结构类型,其中一个在“ a”与“b”中的兼容吗?
  • @EugeneSh。我猜想摆脱这种蠕虫的方法是,最终要比较的是对象的类型兼容性。因此,翻译单元“a”中的struct { int a; int b; } foo; 将与翻译单元“b”中的extern struct { int a; int b; } foo; 兼容,但都不兼容struct {int a; int b; } bar;。而且,翻译单元“a”中的typedef struct { int a; int b } tfoo; 将与翻译单元“b”中的相同类型定义兼容。
  • @JonathanLeffler:您在寻找什么样的用例?我希望这里的规则源于现实。给定包含在多个翻译单元中的包含typedef struct { float x, y; } Point; 的标头,我们希望Point 在这些翻译单元中是“相同”类型,因此是兼容类型。从而证明了跨单元规则的合理性。同时,如果typedef struct { float re, im; } Complex; 在一个单元中声明,则将其视为与Point 不同且不兼容的类型并在代码尝试将一个分配给另一个时报告错误是有好处的……
猜你喜欢
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2014-01-14
  • 2013-04-18
  • 2020-10-28
相关资源
最近更新 更多