简体   繁体   中英

DIfference in structs?

What's the difference between:

typedef struct part 
{
   int a;
} Part;

and

typedef struct 
{
   int a;
} Part;

I know the second one is "anonymous" but are they different?

In addition to Mike Seymour answer, here's an example of why:

Linked list for example

// this works
typedef struct part {
    struct part *next;
} Part;

// this doesn't work
typedef struct {
    struct Part *next;
} Part;
// neither this
typedef struct {
    Part *next;
} Part;

In both cases you define a structure type, and a type alias called Part which refers to that type.

In the first case, you also define a structure name part , so the structure type can also be referred to as struct part , or just part in C++.

In the second case, the structure itself has no name (hence "anonymous"), and can only be referred to by the type alias. Since that alias is only declared after the structure definition, the structure cannot refer to itself.

And in addition to @EoiFirst 's answer,

typedef struct part 
{
   int a;
   struct part *next;
} Part;

This is valid because next is a pointer to struct part , so it has the size of a pointer-type.

C is a typed language, so the compiler knows the type of next , and after struct part is fully defined, it will be able to determine that the code below is valid. It knows that next is a pointer to struct part , that has a field int a .

void test(struct part *p) {
    if (p != NULL && p->next != NULL) {
        printf("%d\n", p->next->a); // this is valid
    }
}

You could declare

typedef struct part 
{
   int a;
   void *next;
} Part;

The size of struct part would still be the same as the declared above. Now next is a pointer to anything, and the code with test() above would compile with error.

warning: dereferencing 'void *' pointer
error: request for member 'a' in something not a structure or union

You would need to write printf("%d\\n", ((struct part *) p->next)->a);

Also, you will not be able to declare this,

typedef struct part 
{
   int a;
   struct part nested;
} Part;

You will get a compiler error.

error: field 'nested' has incomplete type

@MikeSeymur and others gave great answers. I want to add an important point nobody stated explicitly.

In large projects it is important to keep headers rather minimal and avoid #include -ing other headers unless absolutely necessary.

Assume that your structure is defined in some header file part.h . The named structure type Part defined allows other who use your code to skip by using so called "forward-declaration": ”:

//file foo.h knows struct Part "by name only"
struct Part;
void foo(struct Part* p); //in pure C, works for C++ too
void bar(Part* p); //in C++

In the case of anonymous structure, the file foo.h to the file part.h 文件part.h。

//file foo.h forced to #include part.h because "part" is typedef of anonymous type
#include "part.h"
void foo(part* p); 

In legacy code quite often these anonymous types lead to a situation when every header includes so many other headers that maintenance and code reuse become a nightmare.

In general I would suggest not to use the anonymous types unless you know precisely what you are doing (there is a number of cases when they are completely OK, eg as implementation members of other types).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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