【问题标题】:Is the reason that each structure have different types explainable? [closed]每个结构具有不同类型的原因是否可以解释? [关闭]
【发布时间】:2016-06-15 23:46:30
【问题描述】:

例如,由于可能的对齐,指向不同类型的指针不能直接相互转换(也许不是完全正确的陈述,但你还是不明白我的想法)。是否有类似的技术原因导致您不能这样做:

struct A
{
    int a, b;
} ;

struct B
{
    int a, b;
} ;

void func(struct A a, struct B b)
{
    a = b;
}

现在删除我并编辑这个问题,如果你理解它(在某些奇怪的情况下)并将它翻译给公众。

【问题讨论】:

  • 考虑类型 - 苹果和橙子。他们是一样的吗?两者都可以根据果汁含量和体积来定义。即两个值。但是你会比较它们吗?
  • 决定比较基于结构名称(标签),而不是结构。从长远来看,这对您有利。
  • @JonathanLeffler 究竟如何?
  • static_assert(sizeof a == sizeof b); memcpy(&a, &b, sizeof a);
  • 您的标题也与问题不匹配。标题的答案是“每次”:struct Astruct B 是不同的类型。 (这也是标准所说的)。但随后您的文本提出了一系列模糊的问题,可以概括为“为什么具有相同成员的两个结构不同类型?”

标签: c struct memory-layout


【解决方案1】:

在 c 中,具有相同上下文的两个不同结构何时可以真正创建不同的类型?

他们总是这样。 struct Astruct B 是不同的类型。

struct A {
    int a, b;
} ;

struct B {
    int a, b;
} ;

这是被禁止的原因纯粹是因为它对编译器来说太复杂了还是其他原因?

对于编译器来说并不太复杂。最好将它们分开。如果需要相同,代码可以使用typedef

typedef struct A foo;
typedef struct A bar;

int main(void) {
  foo1 x;
  bar1 y = x;
  struct B z = x; // does not compile
}

为什么不允许struct B z = x;?那就是语言设计。如果防止像下面这样的愚蠢代码。尽管struct JustLikeFILEFILE 具有相同的字段,但在概念上它不是 FILE

void f(void) {
  FILE *f = fopen("abc","r");
  struct JustLikeFILE g = *f;  // does not compile
}

【讨论】:

  • 如果我键入def JustLikeFILE 会怎样?为什么它适用于 typedef 而不是结构。
  • FISOCPP typedef struct JustLikeFILE F_type; 创建与struct JustLikeFILE 相同的别名F_type。不是新类型。
【解决方案2】:

C 标准定义了“类型兼容性”,并且对于要兼容的结构类型,除其他标准外,它们必须使用相同的标记。你的结构使用不同的标签——它们本质上是不同的类型。

您可以在标准中一些措辞复杂的规范中找到肮脏的细节:

ISO/IEC 9899:2011 §6.2.7 兼容型和复合型

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

55) 两种类型不必相同即可兼容。

由于您的两个示例结构具有不同的标签(struct Astruct B),因此它们显然不是兼容的类型。

您的第二个示例使用了两个匿名 struct 类型:

struct { int a, b; } func1();

void func2()
{
    struct { int a, b; } var = func1(); //not allowed
}

标准的不同部分适用于此:

6.7.2.1 结构和联合说明符

¶8 struct-or-union-specifier 中的 struct-declaration-list 的存在声明了翻译单元内的新类型。 struct-declaration-list 是结构或联合成员的一系列声明。

引用的struct-declaration-list是大括号{}中的部分。由于您在一个翻译单元中有两个,它们声明(定义)两种类型,因此不兼容。

你的最后一个例子,typedef int myOrangeInt;typedef int myAppleInt; 说明 C 中的 typedef 没有引入新类型;它只是引入了另一种类型的同义词。在这种情况下,myOrangeIntint 的同义词,myAppleInt 也是如此,因为它们是同一类型的同义词,所以类型是同一类型。

§6.7.8 类型定义

¶3 … typedef 声明不引入新类型,只是指定类型的同义词。 …

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-03
    • 2013-12-16
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 2020-07-06
    相关资源
    最近更新 更多