質問

I was browsing the libgphoto2 repositories and saw this:

struct _PTPObjectHandles {
    uint32_t n;
    uint32_t *Handler;
};
typedef struct _PTPObjectHandles PTPObjectHandles;

Why would somebody want do that instead of just calling the struct PTPObjectHandles and omitting the whole typedef line?

EDIT: I should probably note that _PTPObjectHandles is never again used in the code.

役に立ちましたか?

解決

The most common reason for doing this is simply to make it shorter to type and begin to look like a "real data type".

EG, this:

struct _PTPObjectHandles *ptr1;
int something;
struct _PTPObjectHandles *ptr2;

Simply looks "cooler" if you rewrite it as:

PTPObjectHandles *ptr1;
int something;
PTPObjectHandles *ptr2;

That's the main reason.

However, it also provides the library developer that is making you use it the ability to re-typedef it as something else in the future. I've seen cases (eg, OpenSSL) that changed a typedef from a real struct to a pointer to a struct (for example). (Granted, that didn't work, but you can imagine the case where a typedef does actually change and it would work.)

So, do you have to? No.

Do people do it to try and make code more readable? Yes.

Note that a C++ class is actually doing about the same thing. If you go read a good C++ from the ground up kind of book, you'll find it first starting with a struct and then changing the 'struct' word to 'class' and starting to instantiate it using the straight name.

Edit: And... make sure you read the comment from @Bathsheba below and check proper naming conventions within C. As he points out, it should be _pTPObjectHandles with a lower-case p. For my own style, I avoid using uppercase typedefs too simply because I like my upper-case types to be true classes in C++ and want to know when they're just typedefs. But, again, that's a style choice.

他のヒント

It's partly so you can forward reference the structure inside itself but also use a meaningful name in the rest of the code, this:

struct _mylist
{
    struct _mylist *next;
    /* etc ... */
};

typedef struct _mylist MyList;

Note that switching the order round makes things a little more readable, but you still need the two declarations, thus:

typedef struct _mylist MyList;

struct _mylist
{
    MyList *next;
    /* etc ... */
};

What you can't do is this:

typedef struct { MyList *next; } MyList;

so you have to have the 2 declarations.

I tend to use something similar to the first form, like this:

typedef struct _mylist
{
    struct _mylist *next;
    /* etc ... */
} MyList;

as it makes it fairly clear the two types are meant to be the same.

after that line of code, you can create struct by just using PTPObjectHandles. creating that struct

without typedef struct _PTPObjectHandles aStruct;
with typedef: PTPObjectHandles aStruct;

This pattern is used to say "_PTPObjectHandles is an internal (technical) name, don't use it. Use PTPObjectHandles instead."

Generally, in C, a leading underscore means "this is internal, go away". It's a cheap solution for a language that doesn't have proper name spaces (note: I'm talking about plain C here, not C++).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top