While looking for existing C coding standards I discovered that the GNU and Linux projects officially suggest very different styles. Inside the Linux kernel documentation, Linus Torvalds goes so far as to mock GNU coding standards:
First off, I’d suggest printing out a copy of the GNU coding standards,
and NOT read it. Burn them, it’s a great symbolic gesture.
At this point I wanted to understand the difference between the coding styles of established open source projects. When I say “styles” I mean mainly the source code appearance, and the standards that help to read and maintain the code. Here’s a list of coding styles that I read:
- Linux kernel coding style
- GNU Coding Standards
- Qt Coding Style
- Code Conventions for the Java TM Programming Language (PDF version)
- Style Guide for Python Code
- GNOME Programming Guidelines
- Kdelibs Coding Style
- Mono Coding Guidelines
- Christian Neukirchen’s Ruby Style Guide
- The Unofficial Ruby Usage Guide
Many stylistic aspects can’t be compared directly because they are different languages, but it was interesting to map some of them, for example indentation and maximum line length:
indent | line length | |
Linux | 8 char tabs | 80 |
GNU | 2 spaces | N/A |
Qt | 4 spaces | 100 |
Java | 4 spaces | 80 |
Python | 4 spaces | 79 |
Gnome | 8 char tabs | N/A |
Mono | 8 char tabs | 80 |
Ruby | 2 spaces | 80 |
About indentation, the styles describe differently the indentation of function declarations from the indentation of branches (thanks to TaQ for the Ruby suggestions and to JoeT for the correction on the Java example):
branches | functions | |
Linux | if (foo == 0) { →bar(); →foo = 1; } |
int foo() { →return 0; } |
GNU | if (foo == 0) →{ →→bar(); →→foo = 1; →} |
int foo() { →return 0; } |
Qt | if (foo == 0) { →bar(); →foo = 1; } |
int foo() { →return 0; } |
Java | if (foo == 0) { →bar(); →foo = 1; } |
int foo() { →return 0; } |
Python | if foo == 0: →bar() →foo = 1 |
def foo(): →return 0 |
Gnome | if (foo == 0) { →bar(); →foo = 1; } |
int foo() { →return 0; } |
Mono | if (foo == 0) { →bar(); →foo = 1; } |
int foo() { →return 0; } |
Ruby | if foo == 0 →bar →foo = 1 end |
def foo →0 end |
The naming of variables and functions is one of the first things that is apparent while looking at sample code, and sometimes helps to understand the code:
var names | const names | func names | |
Linux | lower_case | UPPER_CASE | lower_case() |
GNU | lower_case | UPPER_CASE | lower_case() |
Qt | mixedCase | mixedCase | mixedCase() |
Java | mixedCase | UPPER_CASE | mixedCase() |
Python | lower_case | UPPER_CASE | lower_case() |
Gnome | lower_case | UPPER_CASE | lower_case() |
Mono | mixedCase | N/A | CamelCase() |
Ruby | lower_case | UPPER_CASE | lower_case() |
I think that one of the reasons that the coding standards are so different is because the principles that they follow are very subjective: readability, clutter, clarity, they depend on the developer that writes or reads the code. The styles also have to find a compromise between readability and code size: for example mixed case naming occupies less characters than using lower case with underscores, and indenting with tabs occupies less bytes than using spaces; but these advantages are quite negligible in my opinion. The aspect that is important for me is consistency between source files in a project: it helps to read the code the first time, it is useful to understand coding patterns and to follow the execution while debugging. To help with consistency, there’s a tool called indent that helps to enforce some of the coding styles; the default settings of indent enforce the GNU coding standards for indenting. The Linux kernel contains its own tool called Lindent, that is basically a script that calls indent with some parameters. I think it should be a good practice to select a style for a project, stick to it and use tools to enforce the styles before committing a change in the source code repository.
TaQ
2010/12/29
Let me make some contribution here about Ruby:
1 – I didn’t understand why the branches example is different from the others, but you can write it this way:
bar if x==0
You don’t need to use parenthesis if not sending any arguments and you can code with that if style.
2 – Functions:
def foo
0
end
You don’t need the parenthesis if you’re not receiving any arguments (as above), and the last expression on the function/method is returned, don’t need to use return if not necessary.
Balau
2010/12/29
I’ve never coded in Ruby, so I copied the examples found in the guide.
I’m gonna change the example to make it similar to the others.
I think your first code snippet could be compared to the C branches without parentheses:
if (x == 0) bar();
or conditional execution:
(x == 0)?bar():foo();
You are right about the function without arguments and the return method, the guide also has examples that skips them.
Thanks for the suggestions!
Tim Harig
2010/12/29
There are a lot more to coding standards then just line length and indentation. Documentation styles, naming conventions, function size, control structure guidelines, function interfaces, etc all play a part. I was disapointed that your argument didn’t go much deeper.
Michael
2010/12/29
One note (nit)… Linux coding style removes parenthesis if there is only one dependent item in a control structure.
if (foo)
bar();
JoeT
2010/12/29
Whoa, the Java branch statement style is totally wrong! I checked your link to see if your source had the same and it did. The problem is with the HTML is formatted incorrectly. Download the PDF and you’ll see what the coding conventions really are.
Steve
2010/12/29
I honestly think that as long a team agrees upon standards, that is 90% of the battle. From my perspective, I use two spaces for indentations in python, as I think it looks more “laddered”, and I can follow the flow breaks more easily as a result.
79 for the line length sounds good.
big
2010/12/29
i guess perl doesn’t exist anymore. fuck
Alex
2010/12/29
Perl still exists, but why would you need a coding style if nobody can read your code anyway?
The double-indent style of GNU seems pointless, but I guess having an illogical standard is better than having none. I’ve never understood placing accolades on an empty line either, but I guess that’s Java-influence when writing C.
Personally the forced-indentation of Python has grown on me, saves everyone a deal of time arguing about accolades and at least you know what you can expect when you need to grok someone elses code. 4 spaced indents of course, just as Guido told us to.
Joe Klemmer
2010/12/30
This is always one of those topics that can get touchy. Many people have very strong feelings about the “correctness” of their preferred style. I know what looks good to me but, as someone who’s worked as a professional coder, the key is to adhere to the specified standards of the project you’re working on.
As for my preferences, this is my personal coding style for C/C++ and similar languages.
Indent: 4 spaces
Brace matching;
Branches:
if (foo == 0)
{
→bar();
→foo = 1;
}
Functions:
int foo()
{
→return 0;
}
Naming;
Var names: mixedCase
Const names: UPPER_CASE
Func names: CamelCase()
The biggie for me is brace matching (branches). Braces should always match up in the same column. Putting the opening brace after the function or command makes it much more difficult to match up lines. Also, even though C/C++ doesn’t require braces if there’s one line, I usually use them anyway. e.g.
if (a = b)
{
return 0;
}
else
{
return 1;
}
Michael
2010/12/30
One other thing about linux… if (foo == 0) is poor form. Better is if (!foo).
Balau
2010/12/30
Thanks Michael, I think it’s a better form too, in almost all the cases, but since the Linux coding standard didn’t mention it I didn’t put it. Looking at K&R they say (section 3.2):
Dan
2011/01/03
I think you merely scratched the surface with this article.
It is nice that you showed the conventions used by various projects and languages, but
I fail to see a conclusion, recommendation or opinions in your article.
Where do you want to take it from here?
Balau
2011/01/03
Dear Dan,
I wanted to compare coding styles objectively, so I read the standards and extracted a subset of comparable characteristics. I don’t think I’m in the position of suggesting anything of value, because I have little experience in managing multi-developer SW projects (and also little experience in C++, Ruby and Java). Maybe someday I will be able to examine the pros and cons with a subjective point of view, grown from personal (and witnessed) failures and successes.
Andrea
2011/01/08
On the C side it is worth mentioning those two:
FreeBSD style
http://www.freebsd.org/cgi/man.cgi?query=style&apropos=0&sektion=0&manpath=FreeBSD+8.1-RELEASE&format=html
Apache
http://httpd.apache.org/dev/styleguide.html
The “key” is to be consistent across the project.
Also an IDE like NetBeans, but even Eclipse, let you choose a standard coding style or customize it to match your needs.
Also with the IDE if you start with a standard and then don’t feel comfortable with it you can change it later very easily and apply that change to all your files in the project.
keith
2011/04/28
Style vs. standard : The first is purely preferential, the second may actually have enforcement policies in some development environments. To see what I mean, try putting some of your cute hacks through a MISRA-C coding checker (or turn it on in your compiler if it supports MISRA-C checking in the preprocessor).
But if you’re looking for unreadability, go search on “obfuscated C”. There’s actually an annual contest!
TheRedQueen
2014/02/18
Hello,
According to the GNU Coding Standards (5.1 Formatting Your Source Code), the maximum line length is 79 characters. Also, the function definition starts with the name of the function in column one :
int
foo(int i, int y)
{
. . .
return(EXIT_SUCCESS);
}
or
int
foo(i, y)
int i, y;
{
. . .
return(EXIT_SUCCESS);
}
Balau
2014/02/18
I didn’t notice the function names in column one, but when I wrote this article the maximum length was not yet specified: see a snapshot of that time. It’s interesting that they inserted it.