C: return and parentheses

2008-10-02

Please don’t write «return(0);». The parentheses are unnecessary. This request generalises. So the NSIDC should not be writing (on line 90 of cproj.c; some sort of Google codesearch link):

return((cosphi / (sqrt (1.0 - con * con))));

Oh yeah. Gotta love those parentheses; they give a nice warm cuddly feeling and make my expressions feel extra protected.

Program as if you know the language. At least a bit:

return cosphi / sqrt (1.0 - con * con);

There. Isn’t that clearer? More parentheses doesn’t always mean clearer code.

16 Responses to “C: return and parentheses”

  1. Eric TF Bat Says:

    I like that angle: “program as if you know the language”. I encounter too much of the opposite in my daily life — programmers who won’t use simple, obvious, powerful techniques because they worry that other programmers won’t understand. So, if they were using Delphi for example, they might write if (C >= 'A') and (C <= 'Z') then ... instead of if C in ['A'..'Z'] then ... because they think not everyone knows about set notation. I say: there are enough ignorant people out there being mollycoddled! Don’t encourage ignorance in your cow-orkers!

  2. drj11 Says:

    I like your Delphi example, but I can’t help wondering what happens when someone uses é or η. But don’t tell me, I really don’t want to know.

  3. ewx Says:

    Agreed in this case; though taken to its extreme, that maxim would imply memorizing the crazy and broken operator precedence rules of C, and I’d rather people made tasteful use of brackets instead of knowing (and expecting other people to know) the madder bits of the ordering.

  4. Tony Finch Says:

    I like to bracket return expressions to make them look more like the rest of the language. I also cuddle up all opening round brackets to the preceding identifier to avoid the #define trap. I view these quirks at roughly the same level as brace placement.

    I would criticize your WTF example on the grounds of redundancy and inconsistent cuddling.

  5. drj11 Says:

    Indeedy. Everyone draws a different line in the operator precedence table. In practice the best thing to do is work in a community where you’re used to looking at each other’s code (like, you know, reviews, inspection), and build-up a consensus on what’s acceptable.

    It’s also good to know more than you rely on. For example I know that «x >> s + 2» binds as «x >> (s + 2)» but on the rare occasions where I have some sort of non-trivial expression as the shift amount, I’ll still put the parentheses in.

  6. drj11 Says:

    @Tony: There is no #define trap. Unless you simply mean that a function-like macro must have no white space between the identifier and the immediately following parenthesis. I cuddle too, but that’s just because it’s stupid not to.

  7. drj11 Says:

    By the way, for those not paying attention, that’s two sets of unnecessary parentheses around the return expression; not just one, but, count ’em, two! (as well as redundant parentheses around the call to sqrt).

  8. Ferruccio Says:

    It’s a vicious circle. Experienced programmers write code so that beginners can understand it. Beginners don’ t improve their skills as much as they should because they don’t need to. On and on it goes.

  9. Ted Lemon Says:

    Thank you. I’ve worked in too many environments where people “correct” return 0; to return(0); I guess if you’re into continuation-passing, return(0) is not completely silly, but I’m pretty sure that’s not why they’re doing it.

    The solution to all these operator precedence problems, of course, is to just do everything in Lisp. If you put in extra parentheses in Lisp, your program stops working.

  10. Eddie Pasternak Says:

    My favorite:

    inline int getState { return m_state; };

    with the lil’ extra semicolon at the end.

  11. mathew Says:

    You will be delighted to know that Eclipse has a code cleanup mode where it automatically brackets every expression, even if the brackets aren’t necessary.

  12. drj11 Says:

    @Ferruccio: I like your vicious circle, I think that’s spot on.

    @mathew: Ah, if only vi had half as much irony.

  13. Francis Davey Says:

    Part of the problem here is an insanity of programmers (derived itself from an insanity of bad mathematicians) in which the parenthesis is overloaded. Its original, best, and clear use was as a way of controlling the precedence of operators eg 2(3+4) we all learnt at school. We all know that you can transform any precedence based language to one without parentheses by using forward or reverse Polish.

    Aha! But rubbish mathematicians started to use parentheses as a way of indicating that a function was involved, as in the school and university “f(x)” notation. Mathematicians are often very poor at understanding their own syntax which *mostly* doesn’t matter since expert systems (other mathematicians) are reading it, so a great deal of fudge and notational abuse is tolerated.

    This is by no means OK even for them. Trying to educate students to really understand the difference between a function and its trace (for instance) is quite hard. If you start thinking that f(x) is the function and V_i is a vector you will get into trouble one day.

    However, computer language designers have (for the most part) followed this madness by using “()” to indicate a function call. Vomit. So instead of “f x” I write “f(x)”. Now my parenthesis is doing double duty. Of all the things to overload this is the dumbest.

    That return is not a function (and therefore there is no need to use “()”) is something one learns in about the first 10 minutes of writing C (or before) since return is such a useful statement (you don’t need it, but its a bugger to do without). There is really no excuse for “return(0)” nevertheless, with so many computer languages needlessly overusing “()” it is not surprising.

    Use ML.

  14. drj11 Says:

    ML mostly has a lovely syntax, it’s true.

    This sort of nonsense also infects novice ML programmers. You see so many beginners that (correctly) write «f(x+1)», but they don’t understand that the parentheses are not there to denote a function call, they are there to stop f being applied to x directly. «f x + 1» binds as «(f x) + 1». Er, doesn’t it (it’s been a while)? So they really ought to write «f (x+1)» (that is, with a space) to show that they understand what the parentheses are doing.

  15. Francis Davey Says:

    Yes “f x + 1” == “(f x) + 1”.

    I found (on a big ML project) that it became really pleasant to only use () for disambiguation. Mind you it is also pleasant to write Verb Noun, rather than a mixture of Verb(Noun) and Noun.Verb() which is what most modern programming languages force on me (and without very good reason in most places may I add).

    Not only do I have the odd double use of () but I also have to remember whether the verb and/or noun are VO or OV, something that may even change across versions of the language.


  16. I bet you feel stupid now that print is a function in Python 3. If only you’d put in parentheses in ‘print (x)’ all those years, your code would still work. But presumably you worried about your image in the hacker community if you did, and missed them out.

    (Yes yes I know, you’d be shafted either way in ‘print “The answer is”, x’ or whatever. What were they thinking of?)


Leave a comment