tags:

views:

251

answers:

3

Opening up the Postgres codebase, I see that much of the C code is written by having pointers with the -> notation in such a way that:

(foo)->next = 5;

I know that pointer notation has levels of precedence, such that -> = (*foo). and is not the same as *foo.

However, does it mean anything when the parentheses are outside the variable name and de-referencing the address of next or is it merely a convention that is endemic to a coding style?

A: 

It is meaningless. The parenthesis have no effect since the expression inside them is so simple. It's basically

(*(foo)).next = 5;

Which, as you can see, is an extraneous set of parenthesis. If that's how the project is doing it, go for it. Otherwise, I think it looks rather awful, so I would try not to use it.

Chris Lutz
Did you mean '`(*(foo)).next = 5;`'?
Jonathan Leffler
Oh. Right. At least now I feel like there's a reason I can't focus on my homework. Thanks for pointing it out, and thanks to Robert for fixing it.
Chris Lutz
+5  A: 

Its a coding convention that I've not seen before.

But it doesn't change anything.

(foo)->next = 5;

is exactly equivalent to

foo->next = 5;
abelenky
Awesome, thanks. That's what I thought, and found it especially strange since it was everywhere in the codebase.
mduvall
To expand on it, the reason you'd use this construct is as a safety-belt in case foo is a macro. It's the same reason some C style guides (for example FreeBSD's) suggest that all return statements be of the form return (x); instead of just return x;
Benno
Although if `foo` were a macro, it would be wise to have it fully parenthesized, e.g. `#define foo (blargity->blah)`
Adam Rosenfield
+1  A: 

It is a coding convention for safety.

In simple code, where foo is just a pointer, the parens are redundant.

(foo)->next = 5;

However, consider if there is or was the chance that foo might be defined by a macro so it is a more complex expression.

In that case, the parens might be required to avoid a compiler error or, worse, to avoid incorrect precedence. Imagine if it translated to an ugly expression like:

( ++get_foo() )->next = 5;

or a common cast:

( (db_record*)foo_ptr )->next = 5;

Something to bear in mind with idiomatic C code is that macros were often used as an abstraction mechanism for things we might do more explicitly in other languages ;-)

Andy Dent
Any macro that _doesn't_ parenthesize it's expansion is a problem. IMHO it should be the macro's job to ensure its own use safety, not the macro-caller's job.
Chris Lutz