C : typedef 结构名称 {...};VS typedef struct{...} 名称; [英] C : typedef struct name {...}; VS typedef struct{...} name;

查看:20
本文介绍了C : typedef 结构名称 {...};VS typedef struct{...} 名称;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如标题所说,我有这个代码:

As the title says, I have this code:

    typedef struct Book{
        int id;
        char title[256];
        char summary[2048];
        int numberOfAuthors;
        struct Author *authors;
    };


    typedef struct Author{
        char firstName[56];
        char lastName[56];
    };


    typedef struct Books{
        struct Book *arr;
        int numberOfBooks;
    };

我从 gcc 得到这些错误:

I get these errors from gcc :

bookstore.c:8:2: error: unknown type name ‘Author’
bookstore.c:9:1: warning: useless storage class specifier in empty declaration [enabled by default]
bookstore.c:15:1: warning: useless storage class specifier in empty declaration [enabled by default]
bookstore.c:21:2: error: unknown type name ‘Book’
bookstore.c:23:1: warning: useless storage class specifier in empty declaration [enabled by default]

如果我像这样更改 typedef,则不会出现警告和错误:

No warnings and no errors occur if I change the typedefs like this:

    typedef struct{
        char firstName[56];
        char lastName[56];
    } Author;

已搜索C 编程语言,第 2 版 并用谷歌搜索了几个小时,我不明白为什么第一个实现不起作用.

Having searched through C Programming Language, 2nd Edition and googled for a couple of hours, I can't figure out why the first implementation won't work.

推荐答案

这里有几件事情要做.首先,正如其他人所说,编译器对未知类型的抱怨可能是因为您需要在使用它们之前定义类型.更重要的是理解三件事的语法:(1) struct 定义,(2) struct 声明,以及(3) typedef.

There are several things going on here. First, as others have said, the compiler's complaint about unknown type may be because you need to define the types before using them. More important though is to understand the syntax of 3 things: (1) struct definition, (2) struct declaration, and (3) typedef.

定义结构体时,结构体可以命名,也可以未命名(如果未命名,则必须立即使用(将在下面进一步解释这意味着什么)).

When Defining a struct, the struct can be named, or unnamed (if unnamed, then it must be used immediately (will explain what this means further below)).

struct Name {
   ...
};

这定义了一个名为struct Name"的类型,然后可用于声明结构变量:

This defines a type called "struct Name" which then can be used to Declare a struct variable:

struct Name myNameStruct;

这声明了一个名为 myNameStruct 的变量,它是一个 struct Name 类型的结构体.

This declares a variable called myNameStruct which is a struct of type struct Name.

你也可以定义一个结构体,同时声明一个结构体变量:

You can also Define a struct, and declare a struct variable at the same time:

struct Name {
   ...
} myNameStruct;

和以前一样,这声明了一个名为 myNameStruct 的变量,它是一个 struct Name 类型的结构体...... 但它同时定义了类型 结构名称.
该类型可以再次用于声明另一个变量:

As before, this declares a variable called myNameStruct which is a struct of type struct Name ... But it does it at the same time it defines the type struct Name.
The type can be used again to declare another variable:

struct Name myOtherNameStruct;

现在 typedef 只是一种给具有特定名称的类型别名的方法:

Now typedef is just a way to alias a type with a specific name:

typedef OldTypeName NewTypeName;

给定上述 typedef,任何时候使用 NewTypeName 都与使用 OldTypeName 相同.在 C 编程语言中,这对结构体特别有用,因为它使您能够在声明该类型的变量时省略结构体"一词,并将结构体的名称简单地视为一种类型它自己的(就像我们在 C++ 中所做的那样).下面是一个先定义结构体,然后对结构体进行 typedef 的例子:

Given the above typedef, any time you use NewTypeName it is the same as using OldTypeName. In the C programming language this is particularly useful with structs, because it gives you the ability to leave off the word "struct" when declaring variables of that type and to treat the struct's name simply as a type on its own (as we do in C++). Here is an example that first Defines the struct, and then typedefs the struct:

struct Name {
   ...
};

typedef struct Name Name_t;

在上面的 OldTypeName 是 struct Name 和 NewTypeName 是 Name_t.所以现在,声明一个struct Name类型的变量,而不是写:

In the above OldTypeName is struct Name and NewTypeName is Name_t. So now, to declare a variable of type struct Name, instead of writing:

struct Name myNameStruct;

我可以简单地写:

Name_t myNameStruct;

还请注意,typedef 可以与结构定义组合,这就是您在代码中所做的:

typedef struct {
   ...
} Name_t;

这也可以在命名结构时完成,但这是多余的:

This can also be done while naming the struct, but this is superfluous:

typedef struct Name {
   ...
} Name_t;

注意:在上面的语法中,由于您以typedef"开头,因此整个语句是一个 typedef 语句,其中 OldTypeName 恰好是一个结构定义.因此,编译器将右大括号 } 之后的名称解释为 NewTypeName ...它NOT 是变量名(就像在没有 typedef 的语法中一样,在这种情况下,您将同时定义结构体并声明结构体变量).

NOTE WELL: In the syntax above, since you have started with "typedef" then the whole statement is a typedef statement, in which the OldTypeName happens to be a struct definition. Therefore the compiler interprets the name coming after the right curly brace } as the NewTypeName ... it is NOT the variable name (as it would be in the syntax without typedef, in which case you would be defining the struct and declaring a struct variable at the same time).

此外,如果您声明 typedef,但在结尾处省略 Name_t,那么您已经有效地创建了一个 INCOMPLETE typedef 语句,因为编译器考虑了 "struct Name { 中的所有内容... }" 作为 OldTypeName,并且您没有为 typedef 提供 NewTypeName.这就是编译器对您编写的代码不满意的原因(尽管编译器的消息相当神秘,因为它不太确定您做错了什么).

Furthermore, if you state typedef, but leave off the Name_t at then end, then you have effectively created an INCOMPLETE typedef statement, because the compiler considers everything within "struct Name { ... }" as OldTypeName, and you are not providing a NewTypeName for the typedef. This is why the compiler is not happy with the code as you have written it (although the compiler's messages are rather cryptic because it's not quite sure what you did wrong).

现在,正如我上面提到的,如果您在定义结构类型时没有命名它,那么您必须立即使用它来声明一个变量:

Now, as I noted above, if you do not name the struct type at the time you define it, then you must use it immediately either to declare a variable:

struct {
   ...
} myNameStruct;  // declares myNameStruct as a variable with this struct
                 // definition, but the definition cannot be re-used.

或者您可以在 typedef 中使用未命名的结构类型:

Or you can use an unnamed struct type in a typedef:

typedef struct {
   ...
} Name_t;

这个最终的语法就是你在写作时实际所做的:

This final syntax is what you actually did when you wrote:

typedef struct{
   char firstName[56];
   char lastName[56];
} Author;

编译器很高兴.哈.

关于 _t 后缀的评论/问题:

Regarding the comment/question about the _t suffix:

_t 后缀是一种约定,向阅读代码的人表明带有 _t 的符号名称是类型名称(与变量名称相反).编译器不解析,也不知道 _t.

_t suffix is a convention, to indicate to people reading the code that the symbolic name with the _t is a Type name (as opposed to a variable name). The compiler does not parse, nor is it aware of, the _t.

C89,尤其是 C99,标准库定义了许多类型并选择使用 _t 作为这些类型的名称.例如 C89 标准定义了 wchar_t、off_t、ptrdiff_t.C99标准定义了很多额外的类型,比如uintptr_t、intmax_t、int8_t、uint_least16_t、uint_fast32_t等.但是_t不是保留的,也不是专门解析的,也不是编译器注意到的,只是一个很好遵循的约定当您在 C 中定义新类型(通过 typedef)时.在 C++ 中,许多人使用约定以大写开头,例如 MyNewType(与 C 约定 my_new_type_t 相对).HTH

The C89, and particularly the C99, standard libraries defined many types AND CHOSE TO USE the _t for the names of those types. For example C89 standard defines wchar_t, off_t, ptrdiff_t. The C99 standard defines a lot of extra types, such as uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, etc. But _t is not reserved, nor specially parsed, nor noticed by the compiler, it is merely a convention that is good to follow when you are defining new types (via typedef) in C. In C++ many people use the convention to start type names with an uppercase, for example, MyNewType ( as opposed to the C convention my_new_type_t ). HTH

这篇关于C : typedef 结构名称 {...};VS typedef struct{...} 名称;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆