- Lots of programming errors can be avoided by proper usage of tools for compilation & static code analysis.
- For compilation, one should always use -Wall option. For example:
gcc -Wall myprogram.c
For static code analysis, “splint” utility. - The software development environment must have a Makefile, even if one has a single C file. The advantage will become obvious as the number of C files and header files grows over a period of time.
- In a big project, one needs to search for files, function names, variable names, and so on. One can use “cscope” and/or “ctags” utilities for this purpose.
- All programs must follow a good C coding guideline. For Linux and C programming, one should look at guidelines used by Linux kernel developers.
Mentioned below is a derived version of this C coding style used at Sanfoundry.
The code must be indented properly. Use tabspaces for indentation. Web developers should use 2 space characters instead of tab space for web publishing (For example publishing a post on sanfoundry.com).
Indentation level 0 -> align to column 1
Indentation level 1 -> indent by 1 tab to the right of indentation level 0
Indentation level n+1 -> indent by 1 tab to the right of indentation level n
Indentation levels in a switch statement are to align the “switch” and “case” labels in the same column. For example:
switch (var) { case 't': avar = 10; break; case 'u': avar = 20; break; default: break; }
2. Breaking Long Lines and Strings
Don’t put multiple statements on a single line.
Don’t put multiple assignments on a single line either.
Don’t leave whitespace at the end of the lines.
The maximum length of a line should be 80 columns. Statements longer than 80 columns will be broken into sensible chunks. For example:
void fun(int a, int b, int c) { if (condition) printf("Warning this is a long printf with 3 parameters" " a: %u b: %u c: %u n", a, b, c); else next_statement; }
3. Placing Braces and Spaces
Put the opening brace last on the line, and put the closing brace first, thus:
if (x is true) { we do y }
This applies to all non-function statement blocks (if, switch, for, while, do). E.g.:
switch (var) { case 't': avar = 10; break; case 'u': avar = 20; break; default: break; }
However, there is one special case, namely functions: they have the opening brace at the beginning of the next line, thus:
int function(int x) { body of function }
Note that the closing brace is empty on a line of its own, _except_ in the cases where it is followed by a continuation of the same statement, ie a “while” in a do-statement or an “else” in an if-statement, like this:
do { body of do-loop } while (condition);
and
if (x == y) { ... } else if (x > y) { ... } else { ... }
Do not unnecessarily use braces where a single statement will do.
if (condition) action();
and
if (condition) do_this(); else do_that();
This does not apply if one branch of a conditional statement is a single statement. Use braces in both branches.
if (condition) { do_this(); do_that(); } else { otherwise(); }
3.1. Spaces
Use a space after (most) keywords. The notable exception is sizeof. So use a space after these keywords: if, switch, case, for, do, while but not with sizeof keyword. For example:
if(a > b) is bad. if (a > b) is good. for(i = 0; i < n; i++) is bad. for (i = 0; i < n; i++) is good. sizeof (struct file) is bad. sizeof(struct file) is good.
Do not add spaces around (inside) parenthesized expressions. This example is *bad*:
s = sizeof( struct file );
This is good:
s = sizeof(struct file);
When declaring pointer data or a function that returns a pointer type, the preferred use of ‘*’ is adjacent to the data name or function name and not adjacent to the type name. Good examples:
char *p; unsigned strlen(char *ptr); Use one space around (on each side of) most binary and ternary operators, such as any of these: = + - < > * / % | & ^ <= >= == != ? : but no space after unary operators: & * + - ~ ! sizeof typeof alignof __attribute__ defined no space before the postfix increment & decrement unary operators: ++ -- no space after the prefix increment & decrement unary operators: ++ -- and no space around the '.' and "->" structure member operators. Do not leave trailing whitespace at the ends of lines.
3.2 Spaces in function arguments
If a function has multiple arguments, then put a space after comma. For example:
sum(a,b) is bad. sum(a, b) is good. printf("a = %d, b = %dn",a,b) is bad. printf("a = %d, b = %dn", a, b) is good.
4. Naming
Don’t use cute names like ThisVariableIsATemporaryCounter.
Don’t use mixed-case names. Always use lower case names.
For global variables and functions, use meaningful & descriptive names.
For example:
int foo(int); /* foo() is a bad name for global function name */ void encode(char *); /* ecnode() is a good global function name */ void count_active_users(void): /* good descriptive name */
LOCAL variable names should be short, and to the point. If you have some random integer loop counter, it should probably be called “i”. Calling it “loop_counter” is non-productive. Similarly, “tmp” can be just about any type of variable that is used to hold a temporary value. For example:
int i; int tmp; char c; char *p;
5. Commenting
Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment. Generally, you want your comments to tell WHAT your code does, not HOW.
Also, try to avoid putting comments inside a function body.
The preferred style for long (multi-line) comments is:
/*
* This is the preferred style for multi-line comments in the
* source code. Please use it consistently.
*
* Description: A column of asterisks on the left side,
* with beginning and ending almost-blank lines.
*/
6. Macros & Enums
Names of macros defining constants and labels in enums are capitalized. For example:
#define CONSTANT 0x12345
Enums are preferred when defining several related constants.
That’s all Folks.