How Python affected my C/C++ brace style

January 14th, 2011 at 9:23 am

Before I even begin this post, one important disclaimer. When you’re working on some existing body of code, by all means stick to its coding style. Even if you don’t like it. This is the #1 most important advice I can give anyone on coding style (in case you’re wondering, #2 is to be consistent).

In the 12-or-so years I’ve been programming in C and C++, I’ve mostly been using the Allman/ANSI style of braces:

while (x == y)
{
    something();
    somethingelse();

    if (condition)
    {
        do_this();
        do_that();
    }
}
finalthing();

I’m not sure why I picked it from the start – there are some vague memories of it being default in MS Visual C++ 6, although the exact details aren’t important.

As any self-respecting programming newbie, I held on to this style religiously, and was genuinely disgusted by alternative styles like the K&R style:

while (x == y) {
    something();
    somethingelse();

    if (condition) {
        do_this();
        do_that();
    }
}
finalthing();

Over the years, as I found myself in need of editing existing code written in some other style, I became less fervent and preferred consistency. But I still used the ANSI style for any new code I wrote.

A strange thing happened when I began writing a lot of Python code. Python, as you know, doesn’t have braces, which makes it conceptually closer to the K&R style in C:

while x == y:
    something()
    somethingelse()

    if condition:
        do_this()
        do_this()

finalthing()

As Python slowly but firmly caught its place as my favorite programming language, this style started growing on me, and I even began wondering why I don’t use the K&R style for C and C++.

Readability and cleanness is an important strength of Python as a language and an ecosystem. Thankfully, most Python programmers are familiar with PEP 8 which rather strictly defines the coding conventions for Python and is used by the entire standard library, as well as most well-known 3rd party modules.

Far less programmers are familiar with PEP 7, which in a manner similar to PEP 8 dictates the programming style to be used for the official C implementation of Python, as well as extension modules written in C.

When I started contributing to Python and perusing its internals, I noticed that C code written with PEP 7 in mind has the same nice consistency as Python code written in PEP 8 style, and since the brace style advocated by PEP 7 is K&R, I finally broke down and adopted it for my C/C++ coding.

One annoyance I still haven’t resolved with this style is with long conditions. Consider this Python code:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
    do_something()

I find it visually unappealing because it’s hard to discern where the condition ends and where the body of the if starts. I even opened an SO question on the topic a while ago and discovered I’m not the only one struggling with this dilemma. Some interesting ideas were raised, although no one really has a perfect solution for this.

Unfortunately, this problem manifests itself in the K&R brace style in C/C++ for the same reason:

if (cond1 == "val1" && cond2 == "val2" &&
    cond3 == "val3" && cond4 == "val4") {
    do_something()
}

While it doesn’t really exist in ANSI style, because the opening brace on a line of its own cleanly separates the condition from the body:

if (cond1 == "val1" && cond2 == "val2" &&
    cond3 == "val3" && cond4 == "val4")
{
    do_something()
}

Still, K&R brace style (and PEP 7 style in general) is the one I prefer now. Switching brace styles turned out to be not very difficult. But remember that being consistent is still far more important than any single style.

Related posts:

  1. New-style signal-slot connection mechanism in PyQt
  2. bugless coding style
  3. Logical operators in Perl and Ruby
  4. Book review: “Rapid GUI Programming with Python and Qt” by Mark Summerfield
  5. Book review: “The Elements of Style” by W. Strunk Jr. and E.B. White

30 Responses to “How Python affected my C/C++ brace style”

  1. SkilldrickNo Gravatar Says:

    My first programming language was C++, and the book I learnt it from used the K&R style, so I’ve never done it any other way since.

    I’d never seen anything about the ANSI style that made me think it was superior in any way, but that’s an interesting point about conditionals…

    One option of course would be to indent the second line again:

    if (cond1 == "val1" && cond2 == "val2" &&
            cond3 == "val3" && cond4 == "val4") {
        do_something()
    }

    Doesn’t look so appealing there because all the conditions are the same length, but usually they’d vary.

  2. ZeccNo Gravatar Says:

    For a moment there I thought you were going to say you wrote:

    if (cond1 == "val1" && cond2 == "val2" &&
        cond3 == "val3" && cond4 == "val4")
       {
       do_something()
       }

    A style I hate most of all.

  3. karstenNo Gravatar Says:

    That’s my offer:

    if (    cond1 == 'val1'
        and cond2 == 'val2'
        and cond3 == 'val3'
        and cond4 == 'val4'):
        """ """
        do_something()

    with of inspiration taken from “Recommended C Style and Coding Standards”.

  4. ripper234No Gravatar Says:

    I’m coding Java in IntelliJ, and simply pressing Ctrl-Alt-L all the time to reformat the code. At this point, I don’t care which brace format is used, just that it’s consistent (IntelliJ’s native format is K&R.

  5. fefeNo Gravatar Says:

    C is not python. What esthetically works in Python is just plain ugly in C.

  6. Arthur ArtamonovNo Gravatar Says:

    Its very interesting to read who and why have choosen bracket style. Python also now is my favorite language and I have thinked that Allman/ANSI is more Pythonish =].

  7. LivNo Gravatar Says:

    Here’s my solution:
    if (
    cond1 == "val1" && cond2 == "val2" &&
    cond3 == "val3" && cond4 == "val4"
    ) {
    do_something()
    }

    The brackets are still in K&R style and the condition is clearly separated from the body. It takes up two more lines, however.

  8. MarkNo Gravatar Says:

    I use a mix of K&R and ANSI. I default to K&R (brace on same line, even for functions), but revert to ANSI when there is a multiline condition (or many function parameters. It’s the best combo IMHO.

  9. ErnieNo Gravatar Says:

    > When you’re working on some existing body of code, by all means stick to its coding style.

    I agree with this for the most part, however, when I’m given ownership of the code (ie: I will be working on it more than others) then I format it to my style.

  10. Peter GoodmanNo Gravatar Says:

    While this isn’t an all-encompassing solution, I usually do:

    if(cond1 == "val1" && cond2 == "val2"
    && cond3 == "val3" && cond4 == "val4"
    || cond5 == "val5" && cond6 == "val6") {
        ...
    }
  11. GuileNo Gravatar Says:

    I often do the following:

    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'
       ):
        do_something()

    Not really pretty, but clear enough for me.

  12. Christian SonneNo Gravatar Says:

    I would generally use something like this instead:

    if (cond1 == "val1" && cond2 == "val2"
    &&  cond3 == "val3" && cond4 == "val4") {
        do_something()
    }
  13. CybexNo Gravatar Says:

    Actually, Whitesmiths style is much closer to Python style than K & R.
    Also, this style is logically correct because braces are part of the method’s body not of the title. Therefore, braces should be at the same indentation level as the rest of the body.

    Strange, but repulsive K & R style is more popular than Whitesmiths or Allman.

    You can get more info here: http://en.wikipedia.org/wiki/Indent_style#Whitesmiths_style

    while (x == y)
        {
        something();
        somethingelse();
        }
    
    finalthing();
  14. Tim VieiraNo Gravatar Says:

    If your condition is too long you can always make it a function!

  15. Tim HNo Gravatar Says:

    if (foo && bar
    && bat && baz
    && frob && hack) {
    body
    }

  16. Tim HNo Gravatar Says:

    Try again:

    if (foo && bar
     && bat && baz
     && frob && hack) {
        body
    }
  17. José HernándezNo Gravatar Says:

    I discovered an excellent piece of advice: a good way to force oneself to understand a piece of code is to indent it by hand. Doing so makes the code’s structure clearer.

  18. JeffNo Gravatar Says:

    @Jose – Yes, re-writing it in your own, canonical style, renaming the variables etc. Too bad that’s really frowned on in places with large code bases and more than one programmer.

  19. JohnNo Gravatar Says:

    Perhaps:

    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
        # then
        do_something()
  20. TobyNo Gravatar Says:

    I made the switch very quickly from ANSI to K&R style in an ACM programming competition practice when I had a piece of code that read:

    if (cond)
    {
      body;
    }

    and in a fit of quick editing carelessness deleted the line with the if (cond). After wasting valuable minutes chasing the resulting bug it was pointed out to me that K&R style means that if you delete the condition, you also delete the opening brace, and the compiler whinges at you.

    To my mind this is all the justification needed for having the brace on the same line as the conditional. It’s also a really good reason to avoid braceless singleton statements, unless they fit on the same line as the conditional.

  21. The other Tim HNo Gravatar Says:

    The Google C++ style guide uses 2-space indentation, which disambiguates this conditional case:

    if (cond1 == "val1" && cond2 == "val2" &&
        cond3 == "val3" && cond4 == "val4") {
      do_something();
    }

    http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml

  22. Ricardo Soares de LimaNo Gravatar Says:

    I’m used to do like this:
    if (cond1 == "val1" && cond2 == "val2" &&
    cond3 == "val3" && cond4 == "val4") {
    //extra line here
    do_something()
    }

  23. Angry MobNo Gravatar Says:

    Traitor!

  24. MarkNo Gravatar Says:

    An important language design element that people overlook when formatting the curly braces in C, C++, and Java is that they are not optional lexical elements of the conditional and iterative statement grammatical productions. The curly braces belong a grammatical production known as <compound-statement>. For example, the grammatical productions for <if-statement>, <if-else-statement>, <while-statement> in EBNF are:

    <if-statement> ::= “if” ‘(‘ <expression> ‘)’ <statement>

    <if-statement> ::= “if” ‘(‘ <expression> ‘)’ <statement> “else” <statement>

    <while-statement> ::= “while” ‘(‘ <expression> ‘)’ <statement>

    As one can plainly see, neither of these grammatical productions include the curly braces as optional lexical elements. The reason why we can use the curly braces to control a sequence of statements with a conditional or iterative statement is because the non-terminal symbol <compound-statement> appears on the right-hand side of the <statement> grammatical production.

    <statement-list> ::= <statement> | <statement-list> <statement>

    <compound-statement> ::= ‘{‘ <statement-list> }

    <statement> ::= <if-statement> | <if-else-statement> | <compound-statement>

    If the commonly accepted coding practice is to indent statements that are controlled by a statement, then they only consistent way to indent code is GNU. We indent the curly braces to show that the compound statement is controlled by a conditional or iterative statement. We further indent the statement list to show that it is controlled by a compound statement.

    e.g,

    if (some_expression)
      {
         statement1;
         statement2;
         statement3;
         ...
      }
  25. elibenNo Gravatar Says:

    Mark,

    This is an interesting aspect I haven’t considered; thanks for sharing. Do note, however, that functions also have compound_statement as their body according to the syntax, however as far as I know their braces are not indented but appear in column 0.

  26. MarkNo Gravatar Says:

    Unlike the pure Algol derivatives (e.g., Ada, Pascal, Modula, Object Pascal, Oberon et al.), the C family has quite a few grammatical oddities and inconsistencies. For example, as stated above, the curly braces are not optional lexical elements of the iterative or conditional control structures that were inherited from C. However, the group controlling the C++ language specification broke this grammatical separation when they added exception handling to the language. Curly braces are effectively required lexical elements of the <try-block> grammatical production in the ISO/IEC C++ language specification because the <compound-statement> non-terminal immediately follows the “try” keyword.

  27. MarkNo Gravatar Says:

    Oddly, my reason for migrating to K&R style was purely pragmatic. I started with ANSI so I could easily see matching braces. As I became more fluent in C, I retreated to K&R because it permitted more lines of code on the screen and I had been reading a lot of code in the K&R style. Indenting performs the same visual mechanism as a lone opening brace on a line. The limited real estate resources of a 24 line green screen improved my ability to understand a routine when more of it would fit on the screen. Yes, I know readability would improve if the routine were smaller anyway. However, the implementation of a depth-first search with weighted path elements just did not fit! Most of my Smalltalk routines were five lines or less, including the comments.

    On the indenting front, I like tabs; more flame war material. Mixing them with spaces is a poor choice, and many times a subsequent maintainer will not immediately notice. And the default of 8 spaces on *NIX machines also wastes horizontal screen real estate. At this point it is just a habit as most development environments auto indent with whatever is established for the tool.

    My current sadness with PEP8 is the desire for underscores in variable names. My style over several languages evolved to CamelCase for names. This does two things for me. As a fluent typist, I can create those really descriptive names with fewer characters, and it relieves me of frequent use of the underscore character at a reach for my weakest little finger! I guess my solution there is to write everything using my style, so people who follow me must remain consistent and follow the style of the current code …

  28. StephenHNo Gravatar Says:

    It’s ironic that the reason you moved to K&R style was because you admired the consistency of PEP7/8 because of course K&R style isn’t consistent in C/C++. You have to put the opening brace on a separate line for things like class and method definitions.

    Meanwhile all the *drawbacks* you listed are real, plus the most obvious drawback of braces no longer lining up.

    Just don’t see the appeal.

  29. elibenNo Gravatar Says:

    @StephenH,

    Actually most modern styles advocate the opening brace on the same line in class and funtion definitions as well. I’m not sure whether this was part of the original K&R standard.

  30. StephenHNo Gravatar Says:

    No, it wasn’t part of K&R, but I see you are right about many modern styles.

    So, opening brace on same line is as consistent as opening brace on new line.

Leave a Reply

To post code with preserved formatting, enclose it in `backticks` (even multiple lines)