Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么';结构';关键字在C中的结构实例之前?_C_Struct_Typedef - Fatal编程技术网

为什么';结构';关键字在C中的结构实例之前?

为什么';结构';关键字在C中的结构实例之前?,c,struct,typedef,C,Struct,Typedef,假设我在C中定义了一个结构。如果我声明了该结构的一个实例,我必须在它前面包含'struct'关键字 // Define struct struct Book { char title[50]; char author[50]; char subject[100]; int book_id; }; // Instantiate struct int main() { struct Book myBook; } 我的问题:为什么struct关键字必须先于struc

假设我在C中定义了一个结构。如果我声明了该结构的一个实例,我必须在它前面包含'struct'关键字

// Define struct
struct Book {
   char title[50];
   char author[50];
   char subject[100];
   int book_id;
};

// Instantiate struct
int main()
{
    struct Book myBook;
}
我的问题:为什么struct关键字必须先于struct的任何实例化?编译器似乎有足够的信息来推断“Book”是一个结构


我知道你可以通过使用typedef来解决这个问题,但这看起来就像是编译器应该已经知道的锅炉板代码。

由于使用关键字struct,这些类型的union和enum名称可以形成自己的名称空间,而不会与其他实体的名称冲突

比如说

#include <stdio.h>

int main(void) 
{
    struct Book 
    {
        const char *Book;
    } Book = { "The first favorite book" };

    struct Book otherBook = { .Book = "The second favorite book" };

    puts( Book.Book );
    puts( otherBook.Book );

    return 0;
}
#包括
内部主(空)
{
结构书
{
const char*Book;
}Book={“最喜欢的书”};
struct Book otherBook={.Book=“第二喜爱的书”};
放(书,书);
放置(otherBook.Book);
返回0;
}

按照当前的安排,您可以同时拥有
结构书
和名为
Book
的全局/本地符号,该符号不需要与
结构书
相关
struct stat
与名为
stat
的函数一起存在,这是POSIX中使用此功能的一个很好的例子

显然,你可以像C++那样自动完成Type Debug,这样就失去了在一个范围内可能有一个无关的<代码> < < /COD> >和 StuttBoo.<代码>,但是我认为不自动化它会使语法变得更整洁,因为如果你根本不使用<代码> TyPulfS,基本上是上下文无关的语法,而对于

typedef
s(显式或隐式),解析器必须维护当前有效的
typedef
ed类型的上下文


就我个人而言,我更喜欢自动
typedef
ing,而不是让全局范围与同名结构标记共存,因此我:

#define Struct(Nm,...) typedef struct Nm Nm; struct Nm __VA_ARGS__
#define Union(Nm,...) typedef union Nm Nm; union Nm __VA_ARGS__
#define Enum(Nm,...) enum Nm __VA_ARGS__; typedef enum Nm Nm

Struct(Book,{
   char title[50];
   char author[50];
   char subject[100];
   int book_id;
});

(您可能希望将其与一个命名约定一起使用,该命名约定让您知道您正在处理一个结构/联合/枚举(例如,
\u s
,如在
book\u s
)。

在C中,结构和联合都有自己的名称空间,不同于全局名称空间。您必须说
struct
,这样它才知道如何查看struct名称空间。@RaymondChen:标记名称空间在结构、联合和枚举之间共享-例如,不能让
struct foo
union foo
都在同一范围内。标签有自己的名称空间,就像
struct
union
成员一样。所有其他标识符(变量名、函数名、枚举常量等)都集中到“普通标识符”名称空间中。判断这是否是一个足以抵消一直编写
struct
的麻烦的优势(或者使用
typedef
技巧,这在历史上混淆了调试信息)是留给读者的。@MatteoItalia问题是,与其他模块或库中的名称可能会有冲突。使用关键字可以避免这些冲突。不是真的……它只是将类型保留在一个单独的命名空间中,该命名空间仍然在所有包含的库之间共享,因此它有助于防止类型和另一种符号。如果有冲突的函数名(通常会发生这种情况)你也有麻烦。@MatteoItalia你在自相矛盾。如果你说的是单独的名称空间,那么你就是在证实我的说法。你只是不明白你自己在说什么。有一个用于结构的名称空间,一个用于联合的名称空间,还有一个用于所有其他名称空间;它们中的每一个都在所有li之间共享我想说的是,这是一种错误的分离——你希望每个库都有一个名称空间,而不是每种实体都有一个名称空间(不同库之间仍然可能有冲突的名称)。