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?
2 个解决方案
#1
13
C does not allow a storage-class specifier (typedef
, but also static
or extern
) in the declaration of a structure member. This is specified in the syntax of structures and unions declaration in 6.7.2.1p1 in C99.
C在结构成员的声明中不允许存储类说明符(typedef,但也包括static或extern)。这在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中的结构/联合成员,并且在这种情况下可以看到存储类说明符是允许的。
#2
5
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.
通常,结构定义的{和}之间应该出现的唯一事物是结构成员的声明。
As ouah says, a declaration within a struct
definition cannot include a storage class specifier; the storage class specifiers are typedef
, extern
, static
, auto
, and register
(and C11 adds _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.
正如ouah所说,结构定义中的声明不能包含存储类说明符;存储类说明符是typedef,extern,static,auto和register(和C11添加_Thread_local)。这种限制是有道理的,因为结构成员的存储完全取决于它所属的结构的存储。
And typedef
is a special case; it doesn't specify a storage class, but it's treated as a storage class specifier for syntactic convenience.
而typedef是一个特例;它没有指定存储类,但为了方便,它被视为存储类说明符。
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. 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. I'll try to verify with the standard that this is illegal.
更新:gcc -pedantic-errors拒绝此致命错误,表明这是非法的。我会尝试用标准验证这是非法的。
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. For example, I'd rewrite the code in the question like this:
我认为最好的做法是在结构中只有成员声明。如果需要声明另一个类型,请在struct声明之外声明它。例如,我在这样的问题中重写代码:
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;
}
#1
13
C does not allow a storage-class specifier (typedef
, but also static
or extern
) in the declaration of a structure member. This is specified in the syntax of structures and unions declaration in 6.7.2.1p1 in C99.
C在结构成员的声明中不允许存储类说明符(typedef,但也包括static或extern)。这在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中的结构/联合成员,并且在这种情况下可以看到存储类说明符是允许的。
#2
5
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.
通常,结构定义的{和}之间应该出现的唯一事物是结构成员的声明。
As ouah says, a declaration within a struct
definition cannot include a storage class specifier; the storage class specifiers are typedef
, extern
, static
, auto
, and register
(and C11 adds _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.
正如ouah所说,结构定义中的声明不能包含存储类说明符;存储类说明符是typedef,extern,static,auto和register(和C11添加_Thread_local)。这种限制是有道理的,因为结构成员的存储完全取决于它所属的结构的存储。
And typedef
is a special case; it doesn't specify a storage class, but it's treated as a storage class specifier for syntactic convenience.
而typedef是一个特例;它没有指定存储类,但为了方便,它被视为存储类说明符。
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. 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. I'll try to verify with the standard that this is illegal.
更新:gcc -pedantic-errors拒绝此致命错误,表明这是非法的。我会尝试用标准验证这是非法的。
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. For example, I'd rewrite the code in the question like this:
我认为最好的做法是在结构中只有成员声明。如果需要声明另一个类型,请在struct声明之外声明它。例如,我在这样的问题中重写代码:
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;
}