-1

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

struct A
{
    int a, b;
} ;

struct B
{
    int a, b;
} ;

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

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

4

2 回答 2

1

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

他们总是这样做。 struct A并且struct 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 JustLikeFILE具有与 相同的字段,但从FILE概念上讲它不是FILE.

void f(void) {
  FILE *f = fopen("abc","r");
  struct JustLikeFILE g = *f;  // does not compile
}
于 2016-03-02T23:34:29.537 回答
1

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

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

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

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

55)两种类型不必相同才能兼容。

由于您的两个示例结构具有不同的标签(struct A, struct 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;说明了typedef在 C 中没有引入新类型;它只是引入了另一种类型的同义词。在这种情况下,myOrangeInt是 的同义词int, 也是myAppleInt,并且由于它们是同一类型的同义词,因此类型是同一类型。

§6.7.8 类型定义

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

于 2016-03-03T00:44:13.160 回答