Corporate Programming Standards C C++
Corporate Programming Standards C C++
Table of Contents
1 Document..........................................................................................6
1.1 Distribution List ..................................................................................................6
1.2 Editors ................................................................................................................6
1.3 Status .................................................................................................................7
1.4 Document validity...............................................................................................7
1.5 History ................................................................................................................7
1.6 Reviews..............................................................................................................7
1.7 Copyrights ..........................................................................................................8
1.8 Document Confidentially ....................................................................................8
2 Overview ...........................................................................................9
2.1 Introduction ........................................................................................................9
2.2 Scope of this guidelines .....................................................................................9
1 Document
1.2 Editors
Name Department E-Mail
Miran Miksic BD HWD 2 [email protected]
1.3 Status
In progress
Review version
Review status
9 Released
Table 3 Document Status
1.5 History
When extending the history, don’t forget to write the current version number onto the front
page of this document.
Version Date Responsible Sections Changes
WN Software Archi-
1.0 27th July all Initial version
tecture Community
1.6 Reviews
Version Date Responsible Sections Result
WN Software Archi-
1.0 27th July all Version 1.0 released
tecture Community
1.7 Copyrights
Almost all the hardware and software names that appear in this document are registered
trademarks of their respective product owners and should be treated as such. In its references
to product names, Wincor Nixdorf uses the version commonly adopted by the vendors.
2 Overview
2.1 Introduction
This document describes a set of rules, guidelines and recommendations used when writing
the source code for C/C++ programs. It presents a set of specific guidelines for using the fea-
tures of C/C++ in a disciplined manner.
The goal of each developer should be to develop high quality, reliable, reusable, portable
software. For a number of reasons, no programming language can ensure the achievements
of these desirable objectives on its own. Programming must be embedded in a disciplined de-
velopment process that addresses a number of topics in a well managed way.
These guidelines ensure these goals by supporting the developer to program in an easy to
read and easy to maintain, reusable and portable way. By complying with these guidelines it
makes it easier for other developers to read and maintain the source code, because every
code has a consistent “layout”.
These guidelines contain as well syntactical rules, which may be checked by any static code
checker (like being consistent with the indent level), as well as semantic rules. Semantic rules
are harder to check, because in normal cases they require a code review by another software
developer. Both, establishing static code analysis tools and setting up code reviews, are part
the Early QA process.
In general it is required to follow all guidelines listed below. Nevertheless in some special cas-
es it may be even advisable to disregard certain guidelines, e.g. if technical reasons suggest
otherwise.
Wincor Nixdorf is committed to follow open and industry standards. This also applies to Cod-
ing and Code Style rules for our software development departments; therefore, this document
is based on conventions and guidelines from different organizations and well-known authors.
References to external sources are marked as such and may be taking into account when ap-
plying these rules or when looking for further examples of a good coding style.
Many of these rules are not applicable to pure C (in contrast to C++) programs. In such a case
just apply all rules which are usable for C.
Exceptions to certain standards are possible but have to be well justified and approved by QA
See also [6], which in fact references “Large-Scale C++ Software Design” by John Lakos.
See [5], chp. 23
2) Include a global header file (if it exists), which contains e.g. global defines or globally
used data structures. E.g. windows.h is a global header or there might be further
product/department-specific global header files.
3) Include the any other headers in a sequence from general headers to more special-
ized headers.
//..
}
}
wincornixdorfGeometry.h:
namespace wincornixdorf {
class Vector3d {
//..
}
}
The cpp-file:
#include "opengl.h" //contains class “Vector3d”
#include "wincornixdorfGeometry.h" //this one, too!
//..
wincornixdorf::Vector3D myVec = new wincornixdorf::Vector3D(); //take Wincor
Nixdorf’s vector
This also avoids adding prefixes to the class names and identifiers of a public interface.
Namespaces shall begin with a small letter.
int iBillValue = 0;
string strBillDescr;
int lengthInMM = 0;
…is better than this:
int length = 0; //in mm
USHORT usStrange = k + 1; // k not known? VS6 and VS2003 will not complain!
// But even so, we forbid such usage of k
for (USHORT k = 100; k <= 109; k++) {//works for all compilers like ex-
pected
//a redefintion of k is okay here
//do sth.
}
In Visual Studio 6 and Visual Studio 2003 the variable “k” is still known after the
first for-loop. Visual Studio 2008 (and other compilers) will generate an error of you
use “k” after the for-loop (applies also to Java). However, with every compiler you
can redefine a “k” in a second for-loop.
Therefore a counter variable declared in the for-loop header shall not be used after
the loop has finished – even if the compiler does not throw an error. It may only be
used like above: With a new declaration in a second loop.
4.3 Initialization
MyType::MyType() {
usCounterM = 0; //yes
ulValueM1 = ulValue2M = 0; //no
}
If you use initializer lists for your constructor, write the variables in the order of their
declaration.
This helps to avoid naming conflicts with equally named functions that are exported
in libraries.
//better:
//instead of:
power(base, n)
int base, n; {
//.......
}
In the example TIMER is the prefix used by the timer module. Many other mod-
ules/libraries may have a define with the name MAX_VALUE, but not with the pre-
fix TIMER.
…better use:
MyClass Obj("Test"); //Stack -> no delete necessary
string strText(""); //an STL string with a dynamic length
This also implies that static arrays should be replaced by STL containers to manage the
memory dynamically. With this we also avoid access violations and buffer overflows. Espe-
cially static char arrays should be replaced by the STL string or by similar string classes.
See [2], chp. 4.5
Remark: For verly large objects this rule may not always be applicable, because the stack size
will be limited (e.g. 1MB for 32bit Windows).
• new[]/delete[]
over malloc() / free().
Additionally take care that you do not mix up the scalar versions of new / delete with the
vector versions, i.e. new[] and delete[]. If you use the vector version new[] to allocate
memory for an array, you have to take the vector version delete[] to free this memory (and
vice versa). If not, the behaviour of the compiler is undefined and you may encounter memory
leaks.
The same applies to mixtures of malloc / delete and new / free. Do not even think of using
these combinations, you will get undefined behaviour!
Of course you can also use references if you don’t want to modify the object. This can be the
case if the object is very large and shall not get copied (performance problems). In such a
case use const references, see 5.5.
Also, avoid casting away the const qualifier except to call a const-incorrect function.
Specify whether a pointer itself is constant, the data it points to is constant, both or neither:
char* p1; // non-const pointer, non-const data
const char* p2; // non-const pointer, const data
char* const p3; // const pointer, non-const data
const char* const p4; // const pointer, const data
better
#include <stdio.h>
INT main() {
iSwitch = getBehaviourSwitch();
if (iSwitch == STH_SPECIAL) {
printf("Something special.\n");
}
else {
printf("Something ordinary.\n");
return 0;
}
}
void MotherChildTest() {
Mother* m = new Child(); //Allocates a lot of memory
Unsafe (2):
ULONG ulSmallValue = getUserInput();
doSomething( (USHORT) ulSmallValue );
Safe (2):
Of course you can still make mistakes by using strncpy() etc. But if we compare strcpy() and
strncpy() you have to pass the length as parameter to strncpy(). This helps to remind you or
any other programmer that you have to think of the length of the variables. This does not au-
tomatically avoid errors, but it is a support to reflect upon the length of the string.
switch(value) {
case SENSOR_1 : {
foo();
}
break;
case SENSOR_2 : {
bar();
}
break;
}
//
//NOT okay:
//
switch(value) {
case 25 ://Sensor 1
{
foo();
}
break;
case 35 ://Sensor 2
{
bar();
}
break;
}
private:
}
Depending on sRc’s value in the example, the number of messages is increased or not. Avoid
such shortcuts.
6.10.3 Use a blank after semicolons if it does not delimit a code line.
for (i = 0; i < 10; i++)
Reason: Comment the “why” not “what”. Such trivial comments distract the reader of the code
and pollute the code with unnecessary remarks. If source code is read by a new programmer,
comments draw attention to themselves, because the reader expects an explanation of the
source code to deepen his understanding. Trivial comments draw attention to the wrong
places. Later on, the reader may not identify comments that really matter and explain some
complex piece of code.
or
• there must be an additional explanation comment.
This has to explain
1) Why and when the code was commented out
2) Under which circumstances this code block can get removed completely in the
future or under which circumstances this code block shall be taken back into
the code.
Reason: Out commented lines are confusing, because a new developer does
not know if this code was important or unimportant, if an error may have sth.
to do with this out commented code block, and so he has to understand and
analyse this code block, too. He may even have to check this code block back
in, compile the program and check for a different behaviour!
The methods of the class (see 7.5) and the members of the class (see 7.6) must also be
commented in the header file.
Here we print the more detailed description of this function. There's no special com-
mand for the long description, there must only be a blank line between this and the
brief description.
\return WORD
API_OK - success
API_AVER_PERI - warning: read status sent by the
API_ERR_SYSTEME - an error occurred
API_ERR_PERI_ABSENT - peripheral or driver not installed
API_ERR_PERI_HORS_SERVICE - peripheral is not in service
API_ERR_PERI_HANDLE - invalid peripheral handle
*/
This header is readable by Doxygen, which can automatically parse all sources and produce
an API description.
This also and especially applies to methods in public interfaces. This helps to keep the docu-
mentation up-to-date.
Note: if you put a # before the return value (e.g. “#API_OK” instead of API_OK) this return
value gets automatically linked if you produce a documentation later. This means that you can
click on “API_OK” in the documentation and you will jump to the definition of API_OK.
Mandatory keywords:
• \file
• \brief
Following the \brief keyword, a mandatory (!) long description follows in a new
line.
Optional Keyword:
• \author
If this is given, the \author should be the responsible developer(s) and not the initial au-
thor(s) of that interface.
These comments are not necessary if a file contains only the declaration (.h) or the implemen-
tation (.cpp) of a class, because in this case the purpose of the file (and therefore the purpose
of the class) is described in the doxygen documentation of the class (with the \class key-
word).
9 Best Practices
In this chapter you will find some best practices and some reminders, which help to avoid
some pitfalls and which can lead to a better design. There could be of course dozens of rules
here – for more information and best practices refer to some interesting books like [5] and [9].
9.1 Distinguish between prefix and postfix forms of increment and dec-
rement operators when overloading operators
// prefix form: increment and fetch
UPInt& UPInt::operator++() {
*this += 1; // increment
return *this; // fetch
}
9.2 Define class type variables using direct initialization rather than
copy initialization.
In constructing both objects 'a1' and 'b1', a temporary String( "Hello" ) is constructed first,
which is used to copy construct the objects. On the other hand, for 'c1' only a single construc-
tor is invoked. Note, some compilers may be able to optimise construction of 'a1' and 'b1' to be
the same as 'c1'; however, conversion rules would still apply, e.g. at most one user-defined
conversion.
String a1 = "Hello"; // avoid
String b1 = String( "Hello" ); // avoid
String c1( "Hello" ); // prefer
9.3 The #define pre-processor directive shall not be used to create in-
line macros. Inline functions shall be used instead.
Inline functions do not require text substitutions and are well-behaved when called with argu-
ments (e.g. type-checking is performed). Example: Compute the maximum of two integers.
#define max (a,b) ((a > b) ? a : b) // Wrong: macro
template class A< int >; // error void foo(int) declared twice
9.5 Only instantiate templates with template arguments which fulfill the
interface requirements of the 'template'.
Using a template argument where some of the requirements for the argument are not met may
cause compilation errors. Implicit instantiation only occurs for the parts of a template definition
that are used.
If an instantiation error is contained in a function definition that is not called then the error will
not be seen unless maintenance leads to that function being called. Explicit template instantia-
tion will instantiate all parts of the template definition, ensuring that the template argument is
valid.
class person {
public:
int getAge( void );
};
doSomething();
}
• dynamic_cast
• reinterpret_cast
• const_cast
Using these, the programmer’s intention becomes much clearer and less error-prone. In the
example above, the following code
char * a = 0;
int b = static_cast<int>(a);
would lead to a compiler error, because there is no legal way for converting a pointer to an in-
teger. In such a case, the programmer would be forced to use the reinterpret_cast operator
and therefore think twice when deciding.
Rule ID Not
Rule Fulfilled NA
Fulfilled
the loop counter inside the loop is avoided?
While loop counter. Is the increment or the decrement of
4.2.9 the loop counters done at the beginning or at the bottom of
the block?
4.3 Initialization
Initialize all variables. Are all variables initialized during
4.3.1
definition?
One initialization per line. Is there only one initialization
4.3.2
per line?
Class name syntax. Are all class names written in
4.4
CamelCase?
4.5 Function syntax rules.
Prefixes for exported C functions. Have exported C
4.5.1 functions (not C++) been uniquely assigned to one module
per prefix?
No prefixes for C++ functions. Have prefixed for C++
4.5.2 functions been avoided and are instead included in a
namespace?
Meaningful names. Have all functions received meaningful
4.5.3
names, which unmistakably describe their purpose?
Function declaration. Is ANSI-C style used for function
4.5.4 declaration, with parameter types in the function declaration
and a return type declared?
4.6 #define syntax rules
The name of a define has to be module specific. Do the
4.6.1
defines have names, which are module specific?
Redefinition of macros is not permitted. Is the
4.6.2
redefinition of macros avoided?
Syntax of macro names. Are all the macro names written
4.6.3
in uppercase?
Table 7 Names and Declarations Check List
Rule ID Not
Rule Fulfilled NA
Fulfilled
Prefer “const” variables or enumerators over #define.
5.8 Have defines being used although const variables would
have been the better alternative?
Avoid compiler switches. Have compiler switches been
5.9
used although runtime switches would have been possible?
Prefer classes over structs. Are classes preferred instead
5.10
of structs in C++ codes?
Downward compatibility. Has every interfaced kept
5.11
downward compatible?
Hide as much data as possible. Have variables and
5.12 methods of all classes been declared as private wherever
this is possible?
Virtual destructors for base classes. Do all base classes
5.13
have virtual destructors?
Method length. Has a method length exceeded 120 lines
5.14
of code?
Range checks on input data. Has each function
implemented a range check on its input data to avoid
5.15
overflows, truncation errors and sign errors, no matter if the
input data is a string or an integer?
Avoid non-range-checking functions. Have all functions
5.16 that don't perform range checking been avoided? (e.g.
strcpy(), strcat(), sprintf(), vsprintf(), gets())
Return value validation. If a function is not defined as
5.17
VOID, is its return value being evaluated by the caller?
Use sizeof. Is sizeof used instead of declaring structure
5.18
lengths?
Avoid machine dependent fill methods. Is the application
of right shift (>>) or left shift (<<) operators to signed
5.19
operands avoided? Is the usage of shifts to perform division
or multiplication avoided?
Don’t trust byte order. Is the writing of code which
5.20 depends on byte order of another architecture or on
particular word alignment boundaries avoided?
Pointer Assignment. Is the assignment of pointers done
5.21
between pointers of same type?
Pointer Validity. Is the validity of a pointer checked by
5.22
comparing it to a typecast NULL?
No Sprintf on overlapping buffers. Has sprintf been used
5.23
on overlapping buffers?
5.24 New[] / delete[]. Was delete[] used for the array new[]?
5.25 Goto. Is the usage of goto avoided?
Avoid magic numbers. Is the usage of constant values
5.26
avoided?
Table 8 Design and programming rules Check List
A 1 List of Tables
Table 1 Document Distribution List ........................................................................................................6
Table 2 Document Editors ......................................................................................................................7
Table 3 Document Status .......................................................................................................................7
Table 4 Document History ......................................................................................................................7
Table 5 Document Reviews ...................................................................................................................7
Table 6 Source Code Structure Check List ..........................................................................................40
Table 7 Names and Declarations Check List .......................................................................................41
Table 8 Design and programming rules Check List .............................................................................42
Table 9 Formatting and notation rules Check List................................................................................43
Table 10 Documentation and commenting Check List.........................................................................44
A 2 Referenced Documents
[1] CERT C++ Secure Coding Standard
https://www.securecoding.cert.org/confluence/display/cplusplus
[2] Peter Thömmes: “C++ Notizen”, Online PDF, Version 2007-11-28
http://www.notes-about-cpp.com
[3] Robert C. Martin: “Clean Code: A Handbook of Agile Software Craftsmanship”, Prentice Hall
International
[4] Clean Code Developer
http://www.clean-code-developer.de/
[5] Herb Sutter, Andrei Alexandrescu: “C++ Coding Standards”, Addison-Wesley
[6] Noel Llopis, Physical Structure and C++ – Part 1: A First Look (seen 2010-02-16)
http://gamesfromwithin.com/physical-structure-and-c-part-1-a-first-look
[7] Doxygen - Source code documentation generator tool
http://www.stack.nl/~dimitri/doxygen/index.html
[8] Simplified Unit Testing for Native C++ Applications
http://msdn.microsoft.com/en-us/magazine/cc136757.aspx
[9] Scott Meyers, “Effective C++ (Third Edition)”, Addison-Wesley