33

我不是初学者,我对以下成语非常熟悉:

typedef struct Foo_ Foo;// I know typedef struct Foo Foo is fine, I'm just trying to make it clearer
struct Foo_
{
    int value;
    Foo *link;
};

我只是突然感到困惑,因为我的理解是在声明之前不允许使用名称(标识符)。但是在声明typedef struct Foo_ Foo中,标识符Foo_还不存在!编译器怎么会允许这种情况发生?请有人对此有所了解,向我解释这种语法的理由是什么?

维基百科引用: 的目的typedef是为现有类型分配替代名称。

--- >8 ---

谢谢大家提供这么多有用的信息。

4

7 回答 7

33

这完全没问题。像你这样的标签的第一次使用struct是类型的前向声明struct

请注意,您的使用_Foo符合要求。保留带有前导下划线和后跟大写字母的标识符。不要那样做。尾随下划线就可以了。

于 2012-11-29T13:00:16.553 回答
14

这在 6.7.2.3p8 中有所介绍:

6.7.2.3 标签

语义
[...]

8 - 如果struct-or-union identifier形式的类型说明符出现在 [a struct-or-union definition] 或 [a struct-or-union declaration] 之外,并且没有其他标识符声明为标记可见,然后它声明一个不完整的结构或联合类型,并将标识符声明为该类型的标记。

struct Fooin 中的类型说明符typedef struct Foo Foo不在定义 ( struct Foo {...};) 或声明 ( struct Foo;) 中,因此它属于 6.7.2.3p8。

请注意, a 没有什么特别之处typedef;你也可以写

struct A { struct Foo *p; };

并且先前的定义或声明不需要是可见的。

但是,在函数声明或定义中:

void foo(struct Foo *p);

如果struct Foo之前没有声明,那么声明的范围将只是函数声明或定义,并且它不会与任何后续声明或定义类型兼容Foo

于 2012-11-29T13:06:51.367 回答
4
ISO c99 : 6.2.1 Scopes of identifiers

7

结构、联合和枚举标记的范围紧随标记出现在声明标记的类型说明符中之后开始。

typedef struct _Foo Foo; // You can do this because it's just the typedef the new type

struct _Foo *myfoo ; // It's pointer to struct _Foo (an incomplete type)
                      //but make sure before using myfoo->value   
                    // struct definition should be available

struct _Foo MyFoo;  // It's  definition of MyFoo but don't forget 
                    // to give the definition of struct _Foo (gcc extension). 

struct _Foo;  // forward declaration

struct _Foo    // It's the definition
{
    int value;
    Foo *link;
};

就像functions我们在实际定义 function 之前一样,所以我们也可以这样forward declaration做。typedefstruct

void func(int );
typedef void (*func_t)(int);

void func(int x)
{
 //actual definition
}
于 2012-11-29T13:13:13.480 回答
3

typedef用于为类型创建别名。但是当 typedef 时,该类型不一定存在。

例如,

如果你这样做:

struct Foo;

而且你永远不会struct Foo在程序中定义任何地方,那么它仍然会编译。编译器会假设它在某处定义并继续。只有在不定义结构的情况下使用它,才会出现错误。

这也是类似的情况typedef

于 2012-11-29T13:01:07.007 回答
1

在某些情况下,struct ...在声明类型之前使用它是有效的。那就是所谓的“不完整型”。

例如,将变量声明为指向“不完整”结构的指针以及(如您所见)a 是有效的typedef

于 2012-11-29T13:00:27.827 回答
1

这称为前向声明。前向声明允许您在允许不完整类型的上下文中使用其名称。

编译器将“看到” typedef 标签,并将其存储起来,直到找到类型为止,所以只要您在 typedef 之后但在任何使用之前声明了类型,就可以了。

于 2012-11-29T13:05:58.433 回答
-2

typedef 声明允许您定义自己的标识符,这些标识符可以用来代替类型说明符,例如 int、float 和 double。typedef 声明不保留存储。

更多信息http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Flanguage%2Fref%2Fclrc03typdef.htm

于 2012-11-29T12:56:32.437 回答