Search This Blog

Monday, March 8, 2010

C Coding Standards : Part 2

//----------------------------------------------
// Createtion date - 08th March, 2010
// Last revision - 09th March, 2010
//----------------------------------------------
4. C Coding Practices:
4.1 Using typedef:
4.1.1 Structs and Enums
The use of typedef with structs and enums is common in C code. Use it to define the structs and enums type which are already defined.
// Correct definition of a struct
struct Foo
{
int x;
int y;
};

typedef struct Foo* pFoo;
// Incorrect definition of an enum
typedef enum _Bar
{
FIRST,
SECOND
} Bar;

Be cautious, the ‘typedef’ directive DOES NOT CREATE A NEW TYPE. It is a compiler level #define. As a result, the following produces a linking error:
// These two typedefs produce the same output for the compiler
typedef int A;
typedef int B;
void MyFunc( A a );
void MyFunc( B b );

(These produce the linking/compiler error that the function "void MyFunc( int )" was defined twice, since both A and B are ‘int’s and are not different types.)
DO NOT OVERUSE IT JUST FOR FUN.

4.1.2 Pointers to Functions
Typedefs are permissible when using pointers to functions. They make the code much cleaner and easier to understand.
int func(int i, bool b);
// Function prototype, defined somewhere
int (*MyFuncPointer) (int, bool);
// Pointer to function
MyFuncPointer = func;
// Assign to the pointer;
(*MyFuncPointer) (2, true); // Call
MyFuncPointer(3, false);
// Call
Do not declare pointer to function as
int *MyFuncPointer(int, bool);
Here, MyFuncPointer is a function which returns pointer to integer.

4.2 Comparison:
4.2.1 Constant Comparison

The constant member of a comparison should be placed on the left side of the comparison. This will cause the compiler to issue an error when you accidentally use = instead of ==.
if (0 == x) // good
if (x == 0) // bad bacause could become if (x = 0)

4.2.2 Pointer Comparison
It is recommended that NULL be used to explicitly test against pointers rather than the not (!) operator.
int *p;
if (NULL != p)
{
...
}


4.2.3 Boolean Comparison
Do not test bool return values for equality with true. No assumptions should be made about the bit pattern representing TRUE. Many functions assume that anything non-zero is true. Comparisons for equality of false are permissible because false is always 0. Comparisons should be made for equality or inequality with false or should use the not (!) operator.

4.3 Ternary Operators:
Try to limit the use of the ternary operator (?:) to the assignment of simple values, not complex expressions. Use of nested ternary operators is discouraged.

4.4 If Statements:
In cases where a single statement forms the if then or else clause of an if statement, it is required that the statement be bracketed as a compound statement.
// This is preferred
if (0 == y)
{
y++;
}

// This is not allowed
if (0 == y)
y++;
Else statements should be placed on the next line after the closing brace of the if statement. They should not be on the same line as the closing brace.
if (0 == y)
{
y++;
}
else
{
y--;
}


4.5 Sizeof Oprators:
The sizeof operator should be used with parenthesis around the object of the operator.
int y = sizeof(x); // Correct
int y = sizeof x;
// Incorrect

4.6 Bitwise Operators:
All expressions involving bitwise operators should be parenthesized.
i = ((a & 0xFF) >> 2);

4.7 Named Constants:
Named constants should be declared using all upper-case letters. #define’d values should be avoided if at all possible. It is preferable to declare a const variable over using #define. Const variables allow the compiler to do type checking whereas #define does not. A global ‘const’ has a ‘static’ storage class by default (it is a local variable that is discarded if not used).
// Prefer
const int BLACK = 3;
// to
#define RED 4

4.8 Switch Statements:
4.8.1 Clearly Mark Intentional Fall Through
A common bug with switch statements is failing to break out of the statement after executing the intended code. Each code block in the construction should be ended with a break statement. In the rare case where you intend to execute the following code block, you should comment as follows:
switch (variable)
{
case 1:
x = y + 1;
// Intentionally Falling Through
case 2:
y++;
break;
}


4.8.2 Indentation for Switch Statements
The layout of a switch statement should be as follows:
switch (variable)
{
case ONE:
. . .
break;
case TWO:
. . .
break;
default:
. . .
break;
}

to be continued...

2 comments:

  1. I recommend it to my students.

    ReplyDelete
  2. Thanks for the appreciation Apu. Wait the last bit is yet to come. I am working on that.

    ReplyDelete