C中兼容的类型和结构

Oli*_*rth 20 c gcc type-conversion

我有以下代码:

int main(void)
{
    struct { int x; } a, b;
    struct { int x; } c;
    struct { int x; } *p;

    b = a;   /* OK */
    c = a;   /* Doesn't work */
    p = &a;  /* Doesn't work */

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

无法在GCC(3.4.6)下编译,但出现以下错误:

test.c:8: error: incompatible types in assignment
test.c:9: warning: assignment from incompatible pointer type
Run Code Online (Sandbox Code Playgroud)

现在,从我的理解(当然从C99的标准),是ac应该是兼容的类型,因为他们履行6.2.7节的所有标准,第1款.我试着编译std=c99,也没有用.

想必我对标准的解释是错误的?

附录

顺便说一句,出现这个问题是因为我想声明一些类似模板的宏来包装各种数据类型而不必在任何地方声明命名类型/ typedef的开销,例如一个简单的例子:

#define LINKED_LIST(T)   \
    struct {             \
        T    *pHead;     \
        T    *pTail;     \
    }

...

LINKED_LIST(foo) list1;
LINKED_LIST(foo) list2;

...

LINKED_LIST(foo) *pList = &list1;  /* Doesn't work */
Run Code Online (Sandbox Code Playgroud)

Gio*_*hal 9

struct { int x; }是一个匿名结构标记,两个匿名结构不能具有"相同名称",这是类型兼容性的必要条件.您可以使用声明与非匿名结构兼容的类型typedef.

struct tmp { int x; }; // declare structure tag
typedef struct tmp type1;
typedef struct tmp type2; // declare 3 types compatible with struct tmp
typedef struct tmp type3; // and with each other

type1 a, b;
type2 c;
type3 *p;
b = a;
c = a;
p = &a;
Run Code Online (Sandbox Code Playgroud)

  • 毫无疑问,您可以在代码示例中执行您的建议.但是,规范说"*如果*一个声明带有标签......". (2认同)
  • 与 Oli 相同的评论,在 OP 的示例中,应该应用“不”使用标签声明结构的规则。 (2认同)

tor*_*rak 8

看一下规范草案,我猜你在依赖声明之后的条件:

此外,如果它们的标签和成员满足以下要求,则在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的......

我认为这些都在同一个C文件中被删除的事实意味着它们在一个翻译单元中.

猜测似乎这可以保证当两个C文件包含一个声明类型的头时,那么该类型的实例将是兼容的.

  • 我非常确定标准有意限制了与定义在不同翻译单元中的情况的兼容性(它不会影响使用指针不能互相别名以进行优化的假设的能力). (3认同)
  • 如前所述,6.2.7p1仅适用于跨翻译单元的结构兼容性,不适用于同一文件。在同一文件中,[6.7.2.3p5](http://port70.net/~nsz/c/c99/n1256.html#6.7.2.3p5)表示*结构,联合或枚举类型的每个声明, *不包含[*]声明不同类型的标签。*另外[6.7.2.1p7](http://port70.net/~nsz/c/c99/n1256.html#6.7.2.1p7)说*存在struct-or-union-specifier中的struct-declaration-list在翻译单元内声明了新类型。* (2认同)
  • @Oli(续)上面的两个陈述都支持这样的想法,即每个翻译单元只能定义一次结构. (2认同)

Yao*_*hai 6

结构、联合和枚举的兼容性

在单个源文件中,每个结构或联合定义都会创建一个与任何其他结构或联合类型既不相同也不兼容的新类型。但是,作为对先前定义的结构或联合类型的引用的类型说明符是相同的类型。该标记将引用与定义相关联,并有效地充当类型名称。为了说明这一点,在本例中只有结构体 j 和 k 的类型是兼容的:

struct   { int a; int b; } h;
struct   { int a; int b; } i;
struct S { int a; int b; } j;
struct S k;
Run Code Online (Sandbox Code Playgroud)

可以将兼容的结构分配给彼此。