简体   繁体   中英

Typedef struct declared as two types: “typedef struct x { .. } X, *XPointer”

Sorry if this has been asked before, I wasn't really even sure what to search for to come up with this.

When I create a typedef struct , I usually do something like this:

typedef struct myStruct {
  int a;
  int b;
  struct myStruct *next;
} MyStruct;

So I declare it with MyStruct at the end. Then when I create functions that pass that in as a parameter, I write

int doSomething(MyStruct *ptr){

}

Yet I am collaborating with a friend on a project and I have come across his coding style, which is to also declare *MyStructP like this:

typedef struct myStruct {
  int a;
  int b;
  struct myStruct *next;
} MyStructR, *MyStructP;

And then he uses MyStructP in his functions, so his parameters look like:

int doSomething(MyStructP)

So he doesn't have to use the * in the parameter list. This confused me because when I look at the parameter list, I always look for the * to determine if the arg is a pointer or not. On top of that, I am creating a function that takes in a struct I created and a struct he created, so my arg has the * and his does not. Ultra confusing!!

Can someone give insight/comparison/advice on the differences between the two? Pros? Cons? Which way is better or worse, or more widely used? Any information at all. Thanks!

It is generally considered poor style to hide pointers behind typedefs, unless they are meant to be opaque handles (for example SDL_GLContext is a void* ).
This being not the case here, I agree with you that it's more confusing than helping.

The Linux kernel coding style says to avoid these kinds of typedefs:

Chapter 5: Typedefs

Please don't use things like "vps_t".

It's a mistake to use typedef for structures and pointers. When you see a

 vps_t a; 

in the source, what does it mean?

In contrast, if it says

 struct virtual_container *a; 

you can actually tell what "a" is.

Some people like to go with ideas from Hungarian Notation when they name variables. And some people take that concept further when they name types.

I think it's a matter of taste.

However, I think it obscures things (like in your example) because you'd have to dig up the declaration of the name in order to find its type. I prefer things to be obvious and explicit, and I would avoid such type names.

(And remember, typedef does not introduce a new type but merely a new name that aliases a new type.)

The main good reason why people occasionally typedef pointers is to represent the type as a "black box object" to the programmer and to allow its implementation to more easily be changed in the future.

For example, maybe today the type is a pointer to a struct but tomorrow the type becomes an index into some table, a handle/key of some sort, or a file descriptor. Typedef'ing this way tells the programmer that they shouldn't try things they might normally do to a pointer such as comparing it against 0 / NULL, dereferencing it (eg - directly accessing members), incrementing it, etc., as their code may become broken in the future. Of course, using a naming convention, such as your friend did, that reveals and encodes that the underlying implementation actually is a pointer conflicts with that purpose.

The other reason to do this is to make this kind of error less likely:

myStructR *ptr1, ptr2;
myStructP  ptr3, ptr4;

That's pretty weak sauce as the compiler will typically catch you misusing ptr2 later, but that is a reason given for doing this.

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