views:

1238

answers:

12

I looked through some code and noticed that the convention was to turn pointer types like

SomeStruct*

into

typedef SomeStruct* pSomeStruct;

Is there any merit to this?

+36  A: 

Not in my experience. Hiding the '*' makes the code hard to read.

sigjuice
+3  A: 

This is a matter of style. You see this kind of code very frequently in the Windows header files. Though they tend to prefer the all upper case version instead of prefixing with a lower case p.

Personally I avoid this use of typedef. It's much clearer to have the user explicitly say they want a Foo* than PFoo. Typedef's are best suited these days for making STL readable :)

typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
JaredPar
+29  A: 

This can be appropriate when the pointer itself can be regarded as a "black box", that is, a piece of data whose internal representation should be irrelevant to the code.

Essentially, if your code will never dereference the pointer, and you just pass it around API functions (sometimes by reference), then not only does the typedef reduce the number of *s in your code, but also suggests to the programmer that the pointer shouldn't really be meddled with.

This also makes it easier to change the API in the future if the need arises, for instance using an ID rather than a pointer (or vice versa). Since the pointer was never supposed to be dereferenced in the first place, existing code won't break.

Artelius
Real world example: in OS X, the CoreFoundation framework makes extensive use of this technique, referring to them as "opaque" data types.
htw
Also in OS X: pthread_t is an opaque type; it is typedef'ed to be a pointer to a 'struct _opaque_pthread_t', which is itself an opaque array of bytes.
Adam Rosenfield
Counter example: FILE *fp? Actually, I agree with you, but there is ample precedent for the contrary.
Jonathan Leffler
'Course, if you do this, you don't name the opaque type "pFoo".
MSalters
And the key point is that when you declare a variable of this opaque type, then (outside the library that implements support for the type) you never apply variable->member; you only ever refer to variable and pass it to functions, etc. You don't increment or decrement the variable either.
Jonathan Leffler
Oh wow, I never considered that `FILE *` was completely unnecessary. It would have been nice if they typedef'd that long ago.
Matt Joiner
A: 

None whatsoever.

John Dibling
+14  A: 
Jonathan Leffler
Does this typedef with less punctuation work? "typedef void SigCatcher(int, void (*)(int))(int)"
sigjuice
No; gcc says "error: SigCatcher declared as function returning a function".
Jonathan Leffler
A: 

Win32 API does this with just about every structure (if not all)

POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2

It's nice how it is consistent, but in my opinion it doesn't add any elegance.

dreamlax
Thta's because the Win32 is a C API and it is common in C not C++
Martin York
The question is tagged both C and C++, what's your point exactly?
dreamlax
Yeah this is a good example, of a very commonly used API. +1
Matt Joiner
+4  A: 

This can help you avoid some errors. For example in following code:

int* pointer1, pointer2;

pointer2 is not an int *, it is simple int. But with typedefs this is not gonna happen:

typedef int* pInt;
pInt pointer1, pointer2;

They are both int * now.

Glorphindale
I see that more as a flaw in the C language
Unknown
If you put the * touching pointer1 rather than touching "int", the declaration makes much more sense that pointer2 is not a pointer, just an int.
dreamlax
I think C programmers would argue that using the dereferencing operator when declaring a pointer variable is more of an idiomatic thing. For examine, in K it says that the expression '*ip' is an int."
htw
2 dreamlax: it is still less readable and consistent code, declaring two variables of different types o one line.
Glorphindale
Roalt
But everyone knows this syntax, and it's best to declare and initialize one variable at a time anyway... I seldom if ever write int *pointer1, *pointer2; because in the next line you have two nice pointers with undefined value.
Daniel Daranas
I think that '''int *pointer, *pointer2''' is still vulnerable to mistakes.
Glorphindale
What Roalt meant to say was: 'int \*pointer1' instead of 'int\* pointer1'.
Artelius
@Daniel Daranas: `int *p1 = NULL, *p2 = NULL;`
Matt Joiner
@Matt Joiner You're right. Although I usually use two lines for that anyway.
Daniel Daranas
+2  A: 

Typedef is used to make code more readable, but making pointer as typedef will increase confusion. Better to avoid typedef pointers.

Chand
+2  A: 

It (like so many answers) depends.

In C this is very common as you are trying to disguise that an object is a pointer. You are trying to imply that this is the object that all your functions manipulate (we know it is a pointer underneath but it represents the object you are manipulating).

MYDB   db = MYDBcreateDB("Plop://djdjdjjdjd");

MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);

Underneath MYDB is probably a pointer at some object.

In C++ this is no longer required.
Mainly because we can pass things around by reference and the methods are incorporated into the class declaration.

MyDB   db("Plop://djdjdjjdjd");

db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db);   // This time we can call be reference.
db.destroyDB();     // Or let the destructor handle it.
Martin York
A: 

Some time ago, i'd have answered "no" to this question. Now, with the rise of smart pointers, pointers are not always defined with a star '*' anymore. So there is nothing obvious about a type being a pointer or not.

So now i'd say : it is fine to typedef pointers, as long as it is made very clear that it is a "pointer type". That means you have to use a prefix/suffix specifically for it. No, "p" is not a sufficient prefix, for instance. I'd probably go with "ptr".

Benoît
Unless you don't intend it to be used as a pointer, in which case you can name it what you will. If it's just used to pass stuff around (like a C FILE *), does it matter exactly what it is?
David Thornley
Good point. I was trying to add some pros to the list of cons that had been said against typedef'ing pointers...
Benoît
A: 

The purpose with typedef is to hide the implementation details, but typedef-ing the pointer property hides too much and makes the code harder to read/understand. So please do not do that.


If you want to hide implementation details (which often is a good thing to do), do not hide the pointer part. Take for instance at the prototype for the standard FILE interface:

FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);

here fopen returns a pointer to some structure FILE (which you do not know the implementation details for). Maybe FILE is not such a good example because in this case it could have worked with some pFILE type that hid the fact that it is a pointer.

pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);

However, that would only work because you never mess around with the content that is pointed to directly. The moment you typedef some pointer that you some places modify the code becomes very hard to read in my experience.

hlovdal
+3  A: 

If you do this, you will be unable to create STL containers of const pSomeStruct since the compiler reads:

list<const pSomeStruct> structs;

as

list<SomeStruct * const> structs;

which is not a legal STL container since the elements are not assignable.

See this question .

Dan Hook