简体   繁体   English

为什么内部结构中不允许使用typedef?

[英]Why is a typedef not allowed in the inner struct?

I have a program that defines a typedef struct within an existing typedef struct, and I am wondering why I am getting a compilation error. 我有一个程序,在现有的typedef结构中定义一个typedef结构,我想知道为什么我得到一个编译错误。

Here is the program: 这是程序:

typedef struct Outer
{
    typedef struct Inner
    {
        int b;
    }INNER;


    INNER inner;
    int a; 

}OUTER;

int main()
{ 
    OUTER obj;
    obj.a = 10;
    obj.inner.b=8;
    return 0;
}   

on compilation gives following error :: 在编译时给出以下错误::

test.c:3:5: error:expected specifier-qualifier-list before ‘typedef’
test.c: In function ‘main’:
test.c:17:5: error: ‘OUTER’ has no member named ‘a’
test.c:18:5: error: ‘OUTER’ has no member named ‘inner’  

but, when I changed the program to 但是,当我把程序改为

typedef struct Outer
{
    struct Inner
    {
        int b;
    };

    struct Inner inner;
    int a; 

 }OUTER;

 int main()
 {
    OUTER obj;
    obj.a = 10;
    obj.inner.b=8;
    return 0;
 }   

it compiles successfully. 它编译成功。

Why is typedef not allowed with inner structures? 为什么内部结构不允许使用typedef?

C does not allow a storage-class specifier ( typedef , but also static or extern ) in the declaration of a structure member. C在结构成员的声明中不允许存储类说明符( typedef ,但也包括staticextern )。 This is specified in the syntax of structures and unions declaration in 6.7.2.1p1 in C99. 这在C99中6.7.2.1p1中的结构和联合声明的语法中指定。

/* The compiler will issue a diagnostic for this declaration */ 
struct s {    
    static int a;
};

You can compare 6.7.2.1p1 syntax with the syntax of a declaration where the declarator is not a function parameter or a structure / union member in 6.7p1 and see that in this case the storage-class specifiers are allowed. 您可以将6.7.2.1p1语法与声明的语法进行比较,其中声明符不是函数参数或6.7p1中的结构/联合成员,并且在这种情况下可以看到存储类说明符是允许的。

It's rather odd style to have a typedef inside a struct definition. struct定义中包含typedef是相当奇怪的风格。

Normally the only things that should appear between the { and } of a struct definition are declarations of members of the structure. 通常, struct定义的{}之间应该出现的唯一事物是struct成员的声明。

As ouah says, a declaration within a struct definition cannot include a storage class specifier; 正如ouah所说, struct定义中的声明不能包含存储类说明符; the storage class specifiers are typedef , extern , static , auto , and register (and C11 adds _Thread_local ). 存储类说明符是typedefexternstaticautoregister (并且C11添加了_Thread_local )。 This restriction makes sense because the storage for a struct member is determined entirely by the storage of the structure of which it's a member. 这种限制是有道理的,因为结构成员的存储完全取决于它所属的结构的存储。

And typedef is a special case; typedef是一个特例; it doesn't specify a storage class, but it's treated as a storage class specifier for syntactic convenience. 它没有指定存储类,但为了方便,它被视为存储类说明符

You can have other kinds of declarations inside a struct definition; 可以在结构定义中包含其他类型的声明; for example, as you've seen, you can nest a struct declaration inside another. 例如,正如您所见,您可以将struct声明嵌套在另一个中。 For example, this program is valid (as far as I can tell): 例如,这个程序是有效的(据我所知):

struct outer {
    struct inner {
        int x;
    };                        // line 4
    struct inner foo;
};

int main(void) {
    struct outer obj;
    obj.foo.x = 42;
    return 0;
}

But gcc warns about the nested declaration: 但gcc警告嵌套声明:

c.c:4:6: warning: declaration does not declare anything [enabled by default]

(And before I tried this, I would have assumed it was illegal.) (在我尝试之前,我会认为这是非法的。)

UPDATE : gcc -pedantic-errors rejects this with a fatal error, suggesting it's illegal. 更新gcc -pedantic-errors拒绝此致命错误,表明这是非法的。 I'll try to verify with the standard that this is illegal. 我会尝试用标准验证这是非法的。

I think the best practice is to have only member declarations inside a struct. 我认为最好的做法是在结构中只有成员声明。 If you need to declare another type, declare it outside the struct declaration. 如果需要声明另一个类型,请在struct声明之外声明它。 For example, I'd rewrite the code in the question like this: 例如,我会像这样重写问题中的代码:

typedef struct Inner
{
    int b;
} INNER;

typedef struct Outer
{
    INNER inner;
    int a;

} OUTER;

int main(void)
{
    OUTER obj;
    obj.a = 10;
    obj.inner.b=8;
    return 0;
}

(Actually, I'd write it like this: (实际上,我会这样写:

struct inner {
    int b;
};

struct outer {
    struct inner inner;
    int a;
};

int main(void) {
    struct outer obj;
    obj.a = 10;
    obj.inner.b = 8;
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM