Hi all, I hope everyone of you out there are fine. Lets talk about array.
Array is used everywhere, in every language. It is easy and gives you access to a particular element in less time over linked lists. Yeah, since array elements are always indexed, you can access any of them without knocking other elements.
Now, straight to code. I have used C codes, for your better understanding of the topic (I hope so). An array is a data form that can hold several values all of one type.
To create an array, you need to indicate 3 things -
1. The type of value to be stored in each element. For example, int, char, float and even a struct.
2. The name of the array.
3. The number of the elements in the array. (We can initialize array at run-time, instead of compilation time. Hold on, we will discuss that in later posts.)
int months[12]; is an array. Here, 'int' is the type of the each element of the array 'months'. And the array 'months' can hold 12 values.
Now how to initialize that. You can initialize an array while defining in the following manner -
int months[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Even,
int months[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Compiler will count for you. But, remember you can never use like -
int months[12];
months[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
The most important thing about the array indexing is, it always starts from zero. Not from 1 or any other number. For the example I am using here, months[12] is an array of 12 elements, ranging from months[0] to months[11]. Be careful on this. Whenever you try to access a memory location in your code, the compiler will not warn you about that. Just crashed when executing, if you are not lucky enough. So, here you actually can not access months[12], anyway. It is out of the memory location you have defined for the array.
What compiler does when you are declaring an array
int months[12];
is allocating a sequence of memory location for 12 'int' type of data. First memory location is pointed by months[0] and the last memory location for data is pointed by months[11]. So, what will happen if you try to get the value at location pointed by months[12], which you have not defined for the application. It will try to access the next memory location after months[11] and will show the garbage value(the meaningless value) at that location. And, if the location is inaccessible to the application it will crash.
Let me allow, to show you the internal memory management on this matter. Consider, compiler allocates memory location 1000 to 1047 for the array int months[12]. Here, each memory location can hold one byte data. Now, 'int' needs 4 bytes of memory, and for 12 'int' it requires 48 bytes of memory. Simple enough...
In this way, months[0] uses memory location 1000 to 1003 and months[11] uses memory location 1044 to 1047. I hope you get clear everything so far. So, in next when you call for months[12] it tries to access the memory location 1048 to 1051. If, the OS allows the application to access that chunk of memory location, you get some garbage; otherwise get hanged.
If you are reading this line, I must appreciate your patients. The doc is too technical, I know. I am sorry about that. I shall try to write in less technical way, to make you understand the technical things. Have a nice coding time.
Saturday, December 4, 2010
Thursday, March 18, 2010
C Coding Standards : Part 3 (The Last Part)
//--------------------------------------------
// Creation Date -- 18th March, 2010
// Last Revision -- 14th April, 2010
//-------------------------------------------
5. Comments:
5.1 File Headers:
Every file--both header and source files--should begin with this standard banner comment:
//-----------------------------------------------------
// File: foo.cpp (or .h)
//
// Desc: This is the description of the file.
// Long descriptions should be
// justified/indented like this.
//
// Any notes or multiple paragraphs are
// formatted like this.
//
// 11/2/2000 - subhab – Started this file
// 12/8/2000 – subhab – Fixed bug 12345
// in GetName() method
//
// Copyright (c) 2009-2010, SUBHA Pvt. Ltd. All rights
// reserved.
//------------------------------------------------------
5.2 Function and Method Headers:
Any function with non-obvious functionality, complex behavior, or a large list of input parameters should use a comment like the one below. It is optional for all other methods.
//--------------------------------------------------
// Name: foo()
// Desc: This method does nothing but return TRUE.
// It's just here to show what
// a function header should look like.
// Parameters:
// Parameter1 String used as input
// Parameter2 String used as output
//--------------------------------------------------
5.3 Structure Headers:
It is strongly recommended that all non-trivial structures have a header such as the following:
//--------------------------------------------
// Name: structure stNothing
// Desc: This structure does nothing.
// It's just here to show what
// a structure header should look like.
//--------------------------------------------
5.4 Section Dividers:
Each major section of code should be divided by a header such as:
//-------------------------------------------
// Global data
//-------------------------------------------
5.5 Source Comments:
The use of the // comment format is preferred over the /*…*/ format.
5.5.1 Inline Code Comments:
Inline comments should be included on their own line and should be indented at the same level as the code they are commenting on.
For example:
if (NULL == pFoo)
{
// The pointer is null, we cannot continue.
return E_POINTER;
}
Inline comments are permissible on the same line as the actual code only when giving a brief description of a structure member variable, or parameter. In this case it is a good idea to align the comments for all variables.
For example:
struct stFoo
{
int m_iCount; // used to store the reference count
DWORD m_dwSeed; // store the random seed value
};
5.5.2 Commenting Out Code:
It is preferable to use #if 0 over /*…*/ to comment out code you don’t want compiled. The first style can be safely nested whereas the second cannot. Test against ‘0’ instead of an undefined value because someone might just define that value.
#if 0 // correct, always works
#ifdef NOTDEF // bad – might fail
6. Programming Considerations:
6.1 Performance Considerations:
The following are merely recommendations but ones that will serve you well if you follow them.
6.1.1 Branch Prediction:
Code your if statements so that the most likely case is the true evaluation. The Pentium processor reads the instructions ahead and must flush a lot of work to branch around the true case. Intel’s documentation can provide more information on this subject.
6.1.2 Postpone Local Variable Definitions:
Define a variable right before you use it, not at the top of the block. If you happen to return before getting to where the variable is used, you’ll save a constructor and a destructor call. It may also ease stack use, lessen register pressure, etc.
The exception is when you have an object with a constructor inside a loop. In this case, it may be advantageous to declare the object right before the loop so that it does not have to be constructed and destructed each loop iteration.
6.1.3 Avoid Header File Bloat:
The unnecessary inclusion of header files can cause compilation times to increase, sometimes by a factor of 2 or 3. You can avoid header bloat by forward declaring classes and structs rather than including the header file where they are defined.
It can also be beneficial to use precompiled headers if you have a lot of source files and they are all including the same headers (like stdio.h).
6.1.4 Data Locality and Alignment:
Define the order of structure/class members with the following principles in mind:
largest types first – a fetch of N bytes is fastest by far if the memory is at 0 == (addr % N). If you define some odd BYTE or short members first, the compiler must either add padding to these small members to get your later double members aligned, or it must generate multiple reads to get the doubles. Adhering to this principle, coincidentally, also gets you the smallest struct. Interestingly, same is true of local variables and parameters.
void MyFunc(double dbl, char ch) // Misaligned dbl!
{
if( ch > g_ch ) {
g_ch = ch;
}
if( dbl > g_dbl ) {
g_dbl = dbl;
}
}
// Same function executes 4-5% faster when dbl is aligned.
// _stdcall, _cdecl, _fastcall are all right-to-left ordered
void MyFunc( char ch, double dbl )
{ … }
Members that you access frequently or that you always access a short time from each other should be located near each other in your struct.. The cache lines are 32bytes wide and all memory is cached 32bytes at a time, so if your struct is larger than this, you want to avoid having to fill two cache lines if the members you need could have occupied one.
If you plan on having arrays of structs, consider adding deliberate padding at the end such that no element in the array will begin misaligned or will span a cache-line unnecessarily.
struct STWillMakeUpAnArray
{
double dblKey; // bytes 0-3
float fltX; // 4-7
float fltY; // 8-11
short iZ; // bytes 12, 13 only!
BYTE pad[2]; // Without this, we misalign
// every odd element’s
// dwKey, fltX, and fltY members!
// Arr[3], and others, require 2
// cache-lines, hurting random access.
};
6.1.5 Temporaries and Copies:
Pass-by-Reference can be an easy solution to the problems with pass-by-value and return-by-value.
bool IsFontBold(int iCheck) // Don’t do this
{
return iCheck > gc_iThreshold;
}
inline bool IsFontBold(int &iCheck) // Good!
{
return iCheck > gc_iThreshold;
}
You can achieve the same with pass-by-pointer, the differences being pointers can be NULL, pointers can be reassigned (well, const BigFontClass * const pMyFont couldn’t…), pointers cause ambiguity about who owns the memory, while references have none of these problems. If you call IsFontBold( * pMyFont), you’d have better checked pMyFont for NULL before making the call!
Return-by-value does allow a clever compiler optimization for anonymous temporaries; the compiler has an excellent chance of constructing this object directly into the memory, whereas if a local variable were created first, there would be 2 copy-constructor(/operator=) invocations.
int MyFunc( int ia, int ib )
{
return (ia+ib);
}
int iSum = MyFunc( i1, i2 );
6.1.6 Size == Performance:
In the vast majority of code, the users’ perception of the performance of the code is determined by the binary size. Writing smaller code will improve load times, increase cache performance, etc.
6.2 Clean Coding Style:
6.2.1 Const and Volatile:
Use const liberally. If a variable will not be changed in a function, make it const. If a method will not be changing any member variables, make the function const. This will allow the compiler to catch potential errors which would otherwise be difficult to track down. Use const member functions if possible.
The purpose of volatile is to force an implementation to supress optimization that could otherwise occur.
For example, for a machine with memory-mapped input/output, a pointer to a device register might be declared as a pointer to volatile, in order to prevent the compiler from removing apparently redundant references through the pointer. Except that it should diagonose explicit attempts to change const objects, a compiler may ignore this qualifier.
6.2.2 Test for the Error Case, Not the Success Case:
Code is much more readable if blocks are kept to a minimum. One way to do this is to check for the error case up front rather than checking for the success case and entering a block if successful.
// Do Not Do This
bool MyFunc(int * pInt)
{
if (NULL != pInt)
{
CFoo pFoo = new CFoo();
if (NULL != pFoo)
{
//do something here
}
else
{
return false;
}
}
else
{
return false;
}
// instead, prefer this
bool MyFunc(int * pInt)
{
if (NULL == pInt)
{
return false;
}
CFoo pFoo = new CFoo();
if (NULL == pFoo)
{
return false;
}
// do something here
}
6.2.3 Limit Exit Points From Functions:
Having more than one exit point in a function or method which allocates memory or increments reference counts risks memory leaks. It is difficult to account for all of the various delete or release combinations required if the function exits early. Even if all of these cases are handled, maintenance of the code can be cumbersome at best and fraught with peril at worst. It is therefore recommended that you limit the number of exit points from a function.
Many people will use goto statements to accomplish this. This is not recommended. The use of goto wreaks havoc with the compiler’s ability to optimize code. It cannot be assured of the execution path and so foregoes much of its optimization
6.2.4 Functions Should Be Short:
As a general rule, functions should be able to fully fit onto the screen at one time. Longer functions are harder to maintain and harder to understand. Functions longer than approximately 30 lines should be examined to see if they can’t be broken up into a series of smaller functions. This isn’t a hard and fast rule, but will produce more maintainable code if it is followed.
// Creation Date -- 18th March, 2010
// Last Revision -- 14th April, 2010
//-------------------------------------------
5. Comments:
5.1 File Headers:
Every file--both header and source files--should begin with this standard banner comment:
//-----------------------------------------------------
// File: foo.cpp (or .h)
//
// Desc: This is the description of the file.
// Long descriptions should be
// justified/indented like this.
//
// Any notes or multiple paragraphs are
// formatted like this.
//
// 11/2/2000 - subhab – Started this file
// 12/8/2000 – subhab – Fixed bug 12345
// in GetName() method
//
// Copyright (c) 2009-2010, SUBHA Pvt. Ltd. All rights
// reserved.
//------------------------------------------------------
5.2 Function and Method Headers:
Any function with non-obvious functionality, complex behavior, or a large list of input parameters should use a comment like the one below. It is optional for all other methods.
//--------------------------------------------------
// Name: foo()
// Desc: This method does nothing but return TRUE.
// It's just here to show what
// a function header should look like.
// Parameters:
// Parameter1 String used as input
// Parameter2 String used as output
//--------------------------------------------------
5.3 Structure Headers:
It is strongly recommended that all non-trivial structures have a header such as the following:
//--------------------------------------------
// Name: structure stNothing
// Desc: This structure does nothing.
// It's just here to show what
// a structure header should look like.
//--------------------------------------------
5.4 Section Dividers:
Each major section of code should be divided by a header such as:
//-------------------------------------------
// Global data
//-------------------------------------------
5.5 Source Comments:
The use of the // comment format is preferred over the /*…*/ format.
5.5.1 Inline Code Comments:
Inline comments should be included on their own line and should be indented at the same level as the code they are commenting on.
For example:
if (NULL == pFoo)
{
// The pointer is null, we cannot continue.
return E_POINTER;
}
Inline comments are permissible on the same line as the actual code only when giving a brief description of a structure member variable, or parameter. In this case it is a good idea to align the comments for all variables.
For example:
struct stFoo
{
int m_iCount; // used to store the reference count
DWORD m_dwSeed; // store the random seed value
};
5.5.2 Commenting Out Code:
It is preferable to use #if 0 over /*…*/ to comment out code you don’t want compiled. The first style can be safely nested whereas the second cannot. Test against ‘0’ instead of an undefined value because someone might just define that value.
#if 0 // correct, always works
#ifdef NOTDEF // bad – might fail
6. Programming Considerations:
6.1 Performance Considerations:
The following are merely recommendations but ones that will serve you well if you follow them.
6.1.1 Branch Prediction:
Code your if statements so that the most likely case is the true evaluation. The Pentium processor reads the instructions ahead and must flush a lot of work to branch around the true case. Intel’s documentation can provide more information on this subject.
6.1.2 Postpone Local Variable Definitions:
Define a variable right before you use it, not at the top of the block. If you happen to return before getting to where the variable is used, you’ll save a constructor and a destructor call. It may also ease stack use, lessen register pressure, etc.
The exception is when you have an object with a constructor inside a loop. In this case, it may be advantageous to declare the object right before the loop so that it does not have to be constructed and destructed each loop iteration.
6.1.3 Avoid Header File Bloat:
The unnecessary inclusion of header files can cause compilation times to increase, sometimes by a factor of 2 or 3. You can avoid header bloat by forward declaring classes and structs rather than including the header file where they are defined.
It can also be beneficial to use precompiled headers if you have a lot of source files and they are all including the same headers (like stdio.h).
6.1.4 Data Locality and Alignment:
Define the order of structure/class members with the following principles in mind:
largest types first – a fetch of N bytes is fastest by far if the memory is at 0 == (addr % N). If you define some odd BYTE or short members first, the compiler must either add padding to these small members to get your later double members aligned, or it must generate multiple reads to get the doubles. Adhering to this principle, coincidentally, also gets you the smallest struct. Interestingly, same is true of local variables and parameters.
void MyFunc(double dbl, char ch) // Misaligned dbl!
{
if( ch > g_ch ) {
g_ch = ch;
}
if( dbl > g_dbl ) {
g_dbl = dbl;
}
}
// Same function executes 4-5% faster when dbl is aligned.
// _stdcall, _cdecl, _fastcall are all right-to-left ordered
void MyFunc( char ch, double dbl )
{ … }
Members that you access frequently or that you always access a short time from each other should be located near each other in your struct.. The cache lines are 32bytes wide and all memory is cached 32bytes at a time, so if your struct is larger than this, you want to avoid having to fill two cache lines if the members you need could have occupied one.
If you plan on having arrays of structs, consider adding deliberate padding at the end such that no element in the array will begin misaligned or will span a cache-line unnecessarily.
struct STWillMakeUpAnArray
{
double dblKey; // bytes 0-3
float fltX; // 4-7
float fltY; // 8-11
short iZ; // bytes 12, 13 only!
BYTE pad[2]; // Without this, we misalign
// every odd element’s
// dwKey, fltX, and fltY members!
// Arr[3], and others, require 2
// cache-lines, hurting random access.
};
6.1.5 Temporaries and Copies:
Pass-by-Reference can be an easy solution to the problems with pass-by-value and return-by-value.
bool IsFontBold(int iCheck) // Don’t do this
{
return iCheck > gc_iThreshold;
}
inline bool IsFontBold(int &iCheck) // Good!
{
return iCheck > gc_iThreshold;
}
You can achieve the same with pass-by-pointer, the differences being pointers can be NULL, pointers can be reassigned (well, const BigFontClass * const pMyFont couldn’t…), pointers cause ambiguity about who owns the memory, while references have none of these problems. If you call IsFontBold( * pMyFont), you’d have better checked pMyFont for NULL before making the call!
Return-by-value does allow a clever compiler optimization for anonymous temporaries; the compiler has an excellent chance of constructing this object directly into the memory, whereas if a local variable were created first, there would be 2 copy-constructor(/operator=) invocations.
int MyFunc( int ia, int ib )
{
return (ia+ib);
}
int iSum = MyFunc( i1, i2 );
6.1.6 Size == Performance:
In the vast majority of code, the users’ perception of the performance of the code is determined by the binary size. Writing smaller code will improve load times, increase cache performance, etc.
6.2 Clean Coding Style:
6.2.1 Const and Volatile:
Use const liberally. If a variable will not be changed in a function, make it const. If a method will not be changing any member variables, make the function const. This will allow the compiler to catch potential errors which would otherwise be difficult to track down. Use const member functions if possible.
The purpose of volatile is to force an implementation to supress optimization that could otherwise occur.
For example, for a machine with memory-mapped input/output, a pointer to a device register might be declared as a pointer to volatile, in order to prevent the compiler from removing apparently redundant references through the pointer. Except that it should diagonose explicit attempts to change const objects, a compiler may ignore this qualifier.
6.2.2 Test for the Error Case, Not the Success Case:
Code is much more readable if blocks are kept to a minimum. One way to do this is to check for the error case up front rather than checking for the success case and entering a block if successful.
// Do Not Do This
bool MyFunc(int * pInt)
{
if (NULL != pInt)
{
CFoo pFoo = new CFoo();
if (NULL != pFoo)
{
//do something here
}
else
{
return false;
}
}
else
{
return false;
}
// instead, prefer this
bool MyFunc(int * pInt)
{
if (NULL == pInt)
{
return false;
}
CFoo pFoo = new CFoo();
if (NULL == pFoo)
{
return false;
}
// do something here
}
6.2.3 Limit Exit Points From Functions:
Having more than one exit point in a function or method which allocates memory or increments reference counts risks memory leaks. It is difficult to account for all of the various delete or release combinations required if the function exits early. Even if all of these cases are handled, maintenance of the code can be cumbersome at best and fraught with peril at worst. It is therefore recommended that you limit the number of exit points from a function.
Many people will use goto statements to accomplish this. This is not recommended. The use of goto wreaks havoc with the compiler’s ability to optimize code. It cannot be assured of the execution path and so foregoes much of its optimization
6.2.4 Functions Should Be Short:
As a general rule, functions should be able to fully fit onto the screen at one time. Longer functions are harder to maintain and harder to understand. Functions longer than approximately 30 lines should be examined to see if they can’t be broken up into a series of smaller functions. This isn’t a hard and fast rule, but will produce more maintainable code if it is followed.
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;
}
// 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...
Wednesday, March 3, 2010
C Coding Standards : Part1
//--------------------------------------------------------
// Creation date - 03rd March, 2010
// Last revision - 03rd March, 2010
//--------------------------------------------------------
1. Introduction:
I konw all of you know about C coding and many of you are good in that. So, what the hell is the CODING STANDARD! What shall I get from this black characters written down?
It is quite natural, those above things are giving you a itchy feeling in your brains. Let me explian. When I was merely a student of computer application, writting codes and running that properly and perfectly was enough for me. But after all these years of coding, I understand just working code is not enough. You need to maintain some standards in your coding style.
This makes your codes more orgnaized and readable (edible also), which makes your (and other coders) life easier in future.
2. General Coding Style:
2.1 Tabs:
The editor should be configured to save tabs as four spaces. This ensures that all fixed-character-width (where all the characters have same width) editors view the code in the same way.
2.2 Line Length:
No line should exceed the width of the typical source code editor. This is typically around 80 characters. Lines should not be allowed to "wrap" but rather should have line breaks at the end of each one.
2.3 Statement Indentation:
Each time a new scope is introduced, either through the use of a compound statement or the introduction of braces, the statements contained in the new scope should be indented 4 spaces (1 tab).
2.4 Braces:
2.4.1 Openning Braces
Wars have been fought over whether or not to place the opening brace on the same line as for, if, etc. statements (K&R style) or on the following line (Allman style). Either style is acceptable but it should be used consistently within a code file. The K&R style allows the code to be more compact and thus more eadible, but the opening brace is easily overlooked. The Allman style makes the opening and closing braces clearly visible (what I prefer).
// K&R Style
while (x <= 5) {
printf("Hello");
}
// Allman Style
if (x > 5)
{
printf("Goodbye");
}
if (x > 5)
{
printf("Goodbye");
}
2.4.2 CLosing Braces
It is strongly encouraged that closing braces are accompanied by a comment which indicates what the brace is closing. If there is a significant amount of code or multiple levels of braces surrounding the opening and closing braces, this comment is required.
For Example:
for(int i = 0; i <>
{
...
} // for i
2.5 Use of Blank Lines:
It is acceptable to use a single blank line to separate areas of functionality within a method. No more than a single blank line should be used within the body of a method. Two blank lines should be used to separate the end of one method body from the beginning of another.
2.6 Always Check Return Codes:
If the unexpected happens, it can be hard to track down if code isn’t paying attention to return values of the called functions. For this reason, every function or method that has a return code should have its return code checked by the calling function. This could save hours of debugging time if the function does fail. Any function call where the return code is not checked, should include a comment explaining why the return code is being ignored.
3. Naming Conventions:
3.1 Variable Names:
3.1.1 Naming Your Variables
Variables should be descriptively named (should be nouns or compound nouns). Single-character variables should only be used as counters (i, j) or as coordinates (x, y, z). Except for type or scope decorations, each word should be Capitalized. In the case of single-character variables, capitalization is not expected.
The variable names should be prefixed with data-type. I am giving here a list for it (Please knock me, if I miss any data-type).
short - s
int - i
float - f or, flt
double - dbl
char - ch
unsigned - u
pointer - p
// Good Variable Names
int iNumberOfNodes;
char * pchUserName;
// Bad Variable Names
int n; // cannot tell what n is used for
char * Something; // name is not descriptive
3.1.2 Scope Designation
The scope of a variable should be discernable from the name of the variable. The following decorations should be used:
g_ is used for global variables (should be rare).
No decoration indicates a local variable.
3.2 Function and Method Names:
Function and method names should be in the form of a verb or verb-noun structure as in Print() or PrintName(). The first character in each word should be upper case and no underscores should be used.
to be continued...
Thursday, February 18, 2010
First Note
Hey All,
It's not a motivational script to all of you (though I've asked to write to all of you something like that). And I don't know how to motivate all of you to do blogging (sharing your problems and solutions you are facing in your sphere) , instead of enjoying the time with social network sites (uff, those shits).
Actually, I've doubt whether any one can motivate others to do something/make engage in something for long. The urge must come from within that person. You should know, no one cares whether your world is ending today. Because, no one invited you to it, anyway.
May be I'm saying all these just because of my state of mind right now. You can't feel easy and can't be in so called 'cool' mood, when you see shit stained faces around you and listining to Marilyn Manson. Inspite of these, I will love to use my pencil to share my problems and solutions with all of you, instead of stiring those shits around me.
When I was merely a student, some of guys always tried to put me down. Some of them even were my friends. Some people, who I trusted most, ditched me. And the good thing is that, all those incidents make my nerves of steel. I always charged up myself in all those situations and rose my head above those problems (even I use the technique still today). I loved to be my own wicked god. Now I know - "what I make is what I am, I can't live forever".
I'm telling you all of these, so that you can understand how the World of Madness will slit your teenage wrist.
Many of you don't have any idea about the World of Madness and how bigger it is than the World of Sane. No one is going to sew your stiches, you've to do it by yourself. And, don't waste your time. Pseudo-morals work real well for the weak. And I don't expect you to be so. The World of Sane only can give you for free, is the "middle finger technology".
So, what you can do in this situation? Get your gun. Be selective on your judgements. Grow up, look around, so that no one ever thinks to do that big F with you.
Creating what we're hating, it's the only fear that is there, in your world. Stay, don't go now. "Come into our home, hope you stay".
Be mad with coding.
Thanks and regards,
Subha Basu
It's not a motivational script to all of you (though I've asked to write to all of you something like that). And I don't know how to motivate all of you to do blogging (sharing your problems and solutions you are facing in your sphere) , instead of enjoying the time with social network sites (uff, those shits).
Actually, I've doubt whether any one can motivate others to do something/make engage in something for long. The urge must come from within that person. You should know, no one cares whether your world is ending today. Because, no one invited you to it, anyway.
May be I'm saying all these just because of my state of mind right now. You can't feel easy and can't be in so called 'cool' mood, when you see shit stained faces around you and listining to Marilyn Manson. Inspite of these, I will love to use my pencil to share my problems and solutions with all of you, instead of stiring those shits around me.
When I was merely a student, some of guys always tried to put me down. Some of them even were my friends. Some people, who I trusted most, ditched me. And the good thing is that, all those incidents make my nerves of steel. I always charged up myself in all those situations and rose my head above those problems (even I use the technique still today). I loved to be my own wicked god. Now I know - "what I make is what I am, I can't live forever".
I'm telling you all of these, so that you can understand how the World of Madness will slit your teenage wrist.
Many of you don't have any idea about the World of Madness and how bigger it is than the World of Sane. No one is going to sew your stiches, you've to do it by yourself. And, don't waste your time. Pseudo-morals work real well for the weak. And I don't expect you to be so. The World of Sane only can give you for free, is the "middle finger technology".
So, what you can do in this situation? Get your gun. Be selective on your judgements. Grow up, look around, so that no one ever thinks to do that big F with you.
Creating what we're hating, it's the only fear that is there, in your world. Stay, don't go now. "Come into our home, hope you stay".
Be mad with coding.
Thanks and regards,
Subha Basu
Subscribe to:
Posts (Atom)