Skip to content

Instantly share code, notes, and snippets.

@SepidehAbadpour
Last active July 13, 2019 01:25
Show Gist options
  • Save SepidehAbadpour/6c96d35a0959989d4bd2e54247ebbf5b to your computer and use it in GitHub Desktop.
Save SepidehAbadpour/6c96d35a0959989d4bd2e54247ebbf5b to your computer and use it in GitHub Desktop.
C++ Coding Standards are written down for my own use. This is public because I want to get feedbacks and complete the list

C++ Coding Standards

Variables

1- Name of variabl should correspond with its application

int xx = 0;
int yy = xx + 1;

In the above example, the names xx and yy are not meaningful but in the following example, the names size and maxSize will carry a sense of the corresponding variable's usage in the code. The reader of the code can understand what is going to be stored in the variable just by reading the name of it.

int size = 0;
int maxSize = size + 1;

2- All variables should be defined in the beginning of the function

If you notice rule 1, this will act like an identity card for the function. You can guess the algorithm and behavior of the function to a good extent just by seeing the variables used in the function. So present the identity card in the beginning not in the end. This will increase readability of the code and minimize the risk of redefining a variable and getting compiler errors.

int featureCount()
{
	int sum = 0;
	int i = 0;
	for (i = 0; i < MAX_FEATURES; i++)
		sum += getFeatures(i);
}

3- camelCase naming convention: Variable name should start with lowercase letters. In multi-word variables, each word except the first should start with an uppercase.

Notice:

  • The rule states naming style
  • The rule says not to be afraid of multi-word variables
  • The rule recommends not use to special characters (characters which are typed with the help of modifier keys, Ctrl, Shift and Alt)
  • Programmers usually use characters like _ and __. But it's recommended not to use. Because:
    • You can type variable name more quickly and will not use to keys to write one character.
    • Variable name continuity will be preserved and optical illusion won't cause the reader to see one character as two.
int maxSize; // NOT: int max_size;
int tableCellWidth; // NOT: table_cell_width;

4- Use suitable and different names for variables with same usage.

You'll often define several variables which all have the same usage like intermediate or temporary variables. Don't act like this:

int tmp1, tmp2, …;

Try to choose a suitable name:

int tmpSize, tmpCount, ..;

Remember: naming as tmp1, tmp2, … is like calling the children in a family as child1, child2, …

5- Do not use the suffix s for variables which present number, instead use the prefix n or the suffix List

There are two reasons:

  • You may not see the s by mistake.
  • Usually there are two variables, one with the suffix s and another without it and this will increase the probability of humen error by programmers.

It's recommended to use the suffix List instead of the prefix n but after choosing one, you should use the same style till the end of coding for your project.

int featureList; // NOT: int features
int nLine; // NOT: int lines

6- Variable name should be consistent with its scope.

For example you can use tmp for a variable in block scope or function scope but not for a variable in class scope. So try length of variable's name be proportional with its scope in order to not be confused while reading the code.

Rule of thumbe: Variable name length is proportional to inverse of its scope.

7- Variable name length should be proportional to its concept.

Avoid using excessively lengthy names for variables. You're sometimes allowed to use acronyms and summarize the name based on the variable scope. For example in a small function scope, you may be able to use stuID to store students's identity number but sometimes you'll have to write studentID.

The important rule is: Do not make the code so lengthy by lengthy variable names and also do not make the code confusing by excessively short and summarized variable names.

8- While defining pointers, write the character * adhered to variable not to variable type.

In some standards, it is recommended to stick the character * to variable type but there are disadvantages with this recommendation.

  • The reader may not see * while reading the code and not notice that the variable is a pointer.
  • It is often recommended to define a new variable with typedef for pointers. In fact sticking * to datatype is like defining a new type not naming a variable of pointer type.
RGFeature *feature = NULL, centerFeature; // NOT: RGFeature* feature = NULL, centerFeature;

Also it is emphasized in all C++ books that in examples like the above code, just feature is a pointer notcenterFeature. If you stick * to datatype, this will not be evident in the code.

9- Class variable names should start with the prefix m

In order to increase readability and recognize class variables easily while reading the code, class variable names should start with the prefix m. It is clear that rule 3 should also be considered and name of variable coming after prefix m should start with a capital letter.

class RGFeature
{
	privet:
	int mSize; // NOT: int size_; int _size; int m_size; int msize;
}

10- Name loop counters as i, j, k and if there are more than 3 nested loops, use l, m, n for naming inner loop counters

This has been common among programmers so we try to obey good prevalent rules. Also loop scope is the smallest among block scopes and the rule is consistent with rule 6 and rule 7.

11- Name of classes, types and structures should start with capital letters and proper prefix

The proper prefix is the acronym of company name. Naming in this style will be a way to express the owner of the code. Using capital letters will result to quick discrimination between variable and its type.

class RGFeature
{
	…
};
//NOT: class rgFeature …
//NOT: class RgFeature …

12- All letters of macro names should be capital and words should be separated with an underdash _

Using capital letters will result to quick discrimination between macros and other variables and types. Using _ will also quicken recognition of macros because it is not used in any other case.

#define MAX_SIZE 5
//NOT: #define MAXSIZE 5
//NOT: #define maxSize 5
//NOT: #define max_size 5

13- Function names should start with lowercases just like rule 3 and should express the task of the function

In C programming language, functions are actually variables of pointer type so regarding this, naming functions just like variables is acceptable. In addition function and variable are the same concept in programming.

The important point in function names is that they should be meaningful. It is necessary to recognize the task of a function just by it's name. That will be really helpful in reverse engineering of the code.

For example suppose a function which its task is to calculate the average of an array. The name average would not be suitable because it doesn't imply the concept of calculating and it seems that the function just reads the average value and returns it. Naming this function as calcAverage or computAverage would be more suitable. So consider the following recommendations when naming functions:

1- Functions which read or write class variables should be named as set[var]() or get[var]()

2- Functions which are used for searching should have the prefix find like findMax or findNearestFeature()

3- Functions which are used for initialization should have the prefix init or initialize like initDistance()

4- Functions which return boolean variables should have the prefix is like isEnabled or isActive

5- Sometimes can, has, should will be used instead of is in case 4

Style of writing

14- Don't make your code messy

One of the important points in writing code is that it should be clear. So delete the codes that you have commented right after getting sure that one piece of code is working correctly.

If you have created extra outputs by printf while debugging, delete them right after getting sure that a piece of code is working correctly.

For example consider the following pieces of code, the second one is much easier to debug, read and track than the first.

int scnNum = 0;
int i;
// QStringList clientNames;
QStringList clientIP;
/* RGSceen *scn;
QHBoxLayout *layout = NULL;
setupUi(this);
mConfig = config;
*/
mConfig->get("screen", "name", clientNames);
mConfig->get("screen", "ip", clientIP);
scnNum = clientNames.size();
// if (scnNum == 0 || scnNum != clientIP.size ())
QMessageBox::critical(this, tr("Client Ui"), tr("Invalid screen definition!"));
// else
{
	layout = new QHBoxLayout(this);
	for (i = 0; i < scnNum; i++)
	{
		/* scn = new RGSceen (this, clientIP.at (i));
		scn->pushButton->setText (clientNames.at (i)); */
		layout->addWidget(scn);
	}
int scnNum = 0;
int i;
QStringList clientNames;
QStringList clientIP;
RGSceen *scn;
QHBoxLayout *layout = NULL;
setupUi(this);
mConfig = config;
mConfig->get("screen", "name", clientNames);
mConfig->get("screen", "ip", clientIP);
scnNum = clientNames.size();
if (scnNum == 0 || scnNum != clientIP.size())
	QMessageBox::critical(this, tr("Client Ui"), tr("Invalid screen definition!"));
else
{
	layout = new QHBoxLayout(this);
	for (i = 0; i < scnNum; i++)
	{
		scn = new RGSceen(this, clientIP.at(i));
		scn->pushButton->setText(clientNames.at(i));
		layout->addWidget(scn);
	}
}

15- Don't break the line unnecessarily

While reading a code, jumping to the next line is time-consuming. The reader also may neglect a line due to optical illusion. So do not break the lines unnecessarily in order to not violate rule 14

int findMax (QStringList stringList, int startIndex);
// NOT:
int
findMax (
	 QStringList stringList,
	 int startIndex);

But if the line is so lengthy, in a way that you should use horizontal scrollbar, then break the line based on the following rules.

1- Each function parameter should be in a seperate line with the comma (,) at the end of the line.

2- Operators should always be at the end of the line.

int findMax (
	     QStringList stringList,
	     int startIndex);
// NOT:
int findMax (
	     QStringList stringList, int startIndex);
x = ( a + b +
      c + d );
// NOT:
x = ( a + b
      + c + d );

16- Don't use magic numbers (numbers that just you know what they mean)

Programmers often encounter variables which take a limited number of values. They may take a value for each case in their mind and pass these values to functions or use them in conditional (if) statements instead of cases. For example:

if ( type == 1)
	getSize (type, 2);

But there are disadvantages with this approach.

1- The code is not beautiful

2- The code is obscure.

3- Tracking the code for debugging or reverse engineering is so hard.

So use macros instead of numbers.

#define SURFACE	1
#define AIR 2
#define SUBSURFACE 3
..
..
if (type == AIR)
	getSize (type, SURFACE);

Sometimes it is recommended in C++ books to use enums in such circumstances. But we would not recommend. Because

1- Usind enums will increase compilation time.

2- Compilers produce lots of errors for casts and enums.

3- Lots of types will make tracking the code so hard.

17- Space character ( ) is a beautiful magic tool

Always use white space in the following cases:

1- Before and after operatoros a = b + c \\NOT a=b+c

2- After comma in function parameter lists hanoi (a, b, c) \\NOT hanoi(a,b,c)

3- After ; in loops for (i = 0; i < n; i++) \\NOT for (i = 0;i < n;i++)

4- Before ( and after ) a + b (c) d \\NOT a + b(c)d

5- Between name of the function and ( which comes after it hanoi (a, b, c) \\NOT hanoi(a, b, c)

6- Between keyword and parenthesis hanoi ( int a, int b, int c) \\NOT hanoi (int a, int b, int c)

7- Alignment is very important so use white spaces to keep the code aligned

For example look at the following piece of code:

int findMaxArea(int sizeList[], int count)
{
	int   i;
	float area = 0.0, maxArea = 0.0;
	for (i = 0; i < (count - 1); i++)
	{
		area = sizeList[i] * sizeList[i + 1];
		if (maxArea < area)
		{
			maxArae = area;
		}
	}
	return maxArae;
}

As you see while defining variables, we've tried to use white space in order to i and area be aligned.

The law is to avoid overdoing and underdoing. Meaning that you should use white spaces in a way that your code becomes beautidul, easy to track and retains readability. So do not be constrained to rule 17 but also do not violate it completely

18- Functions with thousands or hundreds lines of code are a complete failure

Remember that functions are not going to be a complete program. Functions are used for abstraction and prevent renewed coding. So if there is a function with several thousands lines of code in your project, it means that the function is a complete program itself which can be divided into several other functions.

Big functions can be divided into another functions

So if there is such function in your project, there's probably a big mistake in the design and implementation and the project should be reviewed. Notice that here by lines of code, we don't mean whitespace or empty lines which are created for readability. The best way to understand whether the function is long or not, is to implement not more than one or two algorithms in a function.

19- Avoid nested commands

Programmers sometimes use commands like this to shorten the project:

a = ((x = sin ( getAngle (feature) / 2.0)) > VALID_SIZE ? 2*x:x);

These commands are hard to understand even for the programmers themselves and it's better to break them down to several other commands.

angle = getAngle (feature) / 2.0;
y = sin (angle);
if (y > VALID_SIZE)
	a = 2 * x;
else
	a = x;

// OR:

a = x;
angle = getAngle (feature) / 2.0;
y = sin (angle);
if (y > VALID_SIZE)
	a = 2 * x;

Obviously the latter code is much easier to understand and debug.

20- #includes should be categorized and placed based on priority

Avoid writing #includes in an irregular manner because it will cause errors in unexpected places. For example consider the following code:

/// sample.h
#ifndef RG_SAMPLE_H
#define RG_SAMPLE_H

class RGSample
{
	…
}
#endif

///sample.cpp
#include "sample.h"
#include "stdio.h"

When compiling this code, the compiler will show you an error inside stdio.h. But why?

Since there is no ; after class definition, the compiler reads the code until reaching the next ; and declares an error in this point. Since the next ; is inside stdio.h, the error will be declared inside stdio.h but in fact the error is in sample.h. This can make programmers confused.

So it is recommended to categorize header files and to place an empty line between each category. Also order them based on accuracy. So obviously system header files will be placed on the top and program header files on the bottom.

#include system header file

#include external library header file

#include library header file

#include program header file

For example:

#include <stdio.h>
#include <stdlib.h>

#include <QWidget>
#include <QObject>

#include <geos.h>
#include <ogr.h>

#include "sample.h"

21- Do not place #includes in header files

There are disadvantages with placing #includes in header files.

1- Since header files are inserted in source files, inserting them to header files will lead to violation of rule 20

2- The probability of compiler errors gets higher

3- The probability of adding unnecessary header files will be higher which will create unnecessary dependency and increase compile time

Of course there are exceptions

1- In 3rd party libraries, there is a header file which all other header files are placed inside it

2- Sometimes a class is consisted of several files but for the sake of easier management, a .h and a .cpp file is created for the class in which all the other header files and source files are written

22- Do not implement any thing in the header files

For two reasons

1- since the header file is inserted in various source files, any problem in the implementation will lead to a lot of compiler errors

2- Sometimes header files should be released but not the implementation

Comments

23- Explain your code by comments

24- Do not use comments for simple and obvious codes

Consider the following code:

max = ( y > x ? y:x); // find max value

Even someone with zero programming knowledge can understand the purpose of this line without any explaination and comment.

24- Follow the standards for comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment