Embedded System Development Coding Reference Guide
Embedded System Development Coding Reference Guide
Embedded System Development Coding Reference Guide
This document is the English edition of ESCR (Embedded System development Coding Reference) [C
language edition] Version 2.0 published by IPA/SEC* in Japan. It is the revised English edition of ESCR
Version 1.1 made available in 2010 in pdf format. Aimed at improving the quality of the source code written
in C language, ESCR collects the important points to be noted as part of the know-how for coding and
organizes them as practices and rules.
The purpose of this document is to be used as a reference guide for establishing coding conventions
in organizations and groups developing embedded software using C language, and for promoting the
standardization of coding styles and uniformity of source code quality. The rules in Ver. 1.1 comply with
C90, which was the most widely used C language standard at the time Ver. 1.1 was published. Recently,
more and more C language programmers are using C99 after it was released as the successive version of
C90. To respond to this trend, MISRA C was revised significantly in March 2013 (and was issued as MISRA
C: 2012). In the process of revising ESCR Ver.1.1 to Ver.2.0, the following two objectives were set to align
with these recent developments in C language standard and MISRA C guidelines:
Make the rules compliant with C99, and easy for the programmers to use the new features
supported by C99;
Make ESCR consistent with MISRA C to which it is correlated, by reviewing and updating
the references to MISRA C according to its significant revisions in 2013.
To secure the continuity from the previous version, Ver. 2.0 follows the same structure as Ver. 1.1. The
practices and rules carried over from the previous version are also numbered the same as in Ver. 1.1. To
support the language specifications that have been extended in C99, various descriptions have been added to
Ver 2.0, including the introduction of new rules, supplementary explanatory texts, and additional compliant
and non-compliant coding examples. Moreover, in this document, the references to the rules in MISRA
C that have been updated as a part of the significant revisions made in 2013 are numbered the same as in
MISRA C: 2012, while the references to the rules in MISRA C that now exist only in the previous version
are numbered the same as in MISRA C: 2004.
We sincerely hope that the effective use of ESCR Ver. 2.0 will lead to the improvement of embedded
software productivity and contribute to the attainment of high-quality software development.
July 2014
Software Reliability Enhancement Center, Technology Headquarters,
Information-technology Promotion Agency, Japan
ii
Preface
In recent years, the scale of embedded software has been expanding and development by
many people is becoming mainstream. In such development projects which have large teams
consisting of engineers with various levels of skills, it becomes extremely necessary to take
measures to balance out the differences of their skills. In particular, measures for creating
high quality source code with consideration to safety, maintainability and portability from the
software implementations standpoint independently from the engineers' skills are crucially
important, and are regarded as the basic physical strength of embedded software development.
One effective means to address this issue is to prepare and utilize coding conventions where
various coding expertise of the experienced are collected up as knowledge. This background
led us to write and edit the "Coding Practices Guide" targeted for those establishing a coding
convention for C language. In the development of this guide, the drafts were drew up by
experts in programming techniques in the Implementation Quality Technical Committee of
the Embedded Software Development Improvement and Promotion Task Force consists of
members of the METI, IPA/SEC and related organizations.
This book is structured by practices categorized according to quality characteristics and
their corresponding rules. We believe the information provided in this book will help to
establish coding conventions that will meet users requirements.
Not only will this book be useful to engineers establishing coding conventions, but it will
also serve as a stimulus for new ways of looking at things with an overview of the C language
characteristics for experienced developers, and for beginners, as a practical textbook which
will be impart the know-how acquired by their predecessors. We hope that use of this book
will lead to improve embedded software productivity and to attain high quality software
development.
March 2006
Embedded Software Development Improvement and Promotion Task Force
Implementation Quality Technical Committee
Preface
iii
Table of Contents
Preface.................................................................................................................................................................. iii
Part
1Overview....................................................................................................... 2
2.1Quality Characteristics...................................................................................................... 9
2.2Quality Characteristics, Coding Practices and Rules..................................................... 14
Part
21
iv
Table of Contents
Part
145
Appendices
155
Table of Contents
Part
1.2
1.3
1.4
1 Overview
W h aare
t aCoding
r e c o d iPractices?
n g p r a c t i c e s?
1.1
1.1What
Creating source code (code implementation) is an inevitable task for developing embedded software. Success or failure of this task greatly affects the quality of the resulting software. C language,
the most commonly used programming language for embedded software development, is said to
give the programmers a relatively extensive writing flexibility. The quality of programs written in
C thus tends to reflect quite clearly the difference in coding skill level between seasoned and lessexperienced programmers. It is undesirable to have source code varying largely in quality, depending
on the programmers individual coding skills and experience. To prevent this risk from leading into
serious quality issues, forward-thinking companies are working proactively toward standardization
of their source codes by establishing coding standards or conventions to be followed organizationwide or group-wide.
Due to such circumstances, there are, in fact, some coding conventions established at the organization or department level that have lost their significance and are no longer strictly observed.
Nevertheless, organizations that have coding conventions, no matter what kind of format they
prepare them in, are at least better than those without any. There are still quite a few that cannot
reach a consensus of the coding convention to be followed internally, and are relying largely on the
programmers individual judgments to decide how the source code should be written.
1.2
1Overview
Target Users
This guide has been written on the assumption that it will be read by the following types of users:
Benefits Gained
The benefits that the users can expect to gain directly from using this guide are as mentioned
above. Moreover, as a result of these benefits, the users may also be able to expect the following
positive effects:
- Can remove the bottleneck in maintaining software quality caused by inconsistent performance of
implementation engineers;
- Can eliminate obvious errors in the source code at an early stage, such as, during the coding phase
or in subsequent reviews.
Practices
Ch a r a c t e r i s tof
i c the
s o fCoding
the Co
d i n g Pr a c t i c e s
1.3
1.3Characteristics
The coding practices in this guide have the following characteristics.
software quality models. The coding practices described in this guide are customs and ideas on
implementation that have been developed to maintain source code quality, and they reflect the basic
concepts of individual coding rules. The coding rules included in this guide have been selected based
on the needs of the current conditions (actual situation with the language specifications and processing systems) after closely examining the various coding conventions existing in the world, and are
presented in the form of established information that supports the corresponding practices. Classification of practices and rules according to quality characteristics makes it easy for the users of this
guide to understand their respective purpose of use in terms of which aspect of quality each of them
is primarily focused on maintaining.
The coding conventions referenced in this guide range from local conventions used in companies
to which the writers and reviewers of this guide belong, to sets of coding rules established and used
widely in different industries, including MISRA C and Indian Hill C Style and Coding Standards. For details, refer to Citations and References at the end of this document.
1Overview
Noteson
onUsing
usingthis
thisGuide
guide
1.4
1.4Notes
Keep the following points in mind when using this guide.
Although Errors in writing possibly classified as coding errors have been excluded from the reference rules, some frequently observed coding errors collected while preparing this guide are exemplified in Part 3 Typical Coding Errors in Embedded Software. This section (Part 3) is especially
recommended to those who are still new to C language and prone to many of these errors. Moreover,
it should also be a useful reference to project teams that find it meaningful to establish rules to prevent coding errors from being caused by such common pitfalls in programming.
C90
This is the C language standard defined in ISO/IEC 9899:1990 Programming Language C. It is
often called C90, where 90 stands for the year ISO/IEC 9899:1990 was published. The C language
standard has been revised and is now C99, making C90 an older version.
C99
This is the C language standard defined in ISO/IEC 9899:1999 Programming Language C. It is
the current standard widely used. Since ISO/IEC 9899:1999 was published in 1999, it is often called
C99.
C11
This is the most recent C language standard defined in ISO/IEC 9899:2011 Programming Language C and thereby is the current C language standard. Since ISO/IEC 9899:2011 was published
in 2011, it is often called C11.
C++
This is the C++ language standard defined in ISO/IEC 14882:2003 Programming language C++.
MISRA C
It refers collectively to the coding guidelines for C language defined by The Motor Industry Software Reliability Association (MISRA) in UK, which include MISRA C:1998, MISRA C:2004 and
MISRA C:2012.
MISRA C:1998
The convention in Citations and References [6]. This is the revised version of MISRA C:1998.
MISRA C:2012
The convention in Citations and References [7]. This is the revised version of MISRA C:2004.
1Overview
QualityCharacteristics
Characteristics
2.1
2.1Quality
For many, speaking of software quality would remind them of bugs. However, in the field of
software engineering, the quality of software as a product is grasped in a broader perspective. This
concept of software product quality is defined in detail and organized systematically in ISO/IEC
25010.
Reliability
Degree to which a
Maturity
system, product or
component performs
specified functions
under specified conditions for a specified
Availability
period of time
Fault Tolerance
Degree to which a system meets needs for reliability under normal operation
Low occurrence of
bugs through
continued use
10
Code Quality
(ISO/IEC 25010)
Maintainability
Code Quality
(ISO/IEC 25010)
Modularity
Degree to
which the
components
are composed
such that a
change to one
component of
the code has
minimal impact on other
components.
Reusability
Degree to
which a code
can be used in
other programs
Analysability
Easiness of
understanding
the code
Modifiability
Easiness of
modifying
the code, and
lowness of
impact from
modifications
Testability
Easiness of
testing and
debugging the
modified code
11
Portability
Degree of
Adaptability
effectiveness and
efficiency with which
a system, product or
component can be
transferred from one
hardware, software or
other operational or
usage environment to
Installability
another
Performance Efficiency
Performance relative
to the amount of
resources used under
stated conditions
Degree to which a product or system can effectively and efficiently be adapted for different or
evolving hardware, software or other operational
or usage environments
Time Behaviour
Degree to which the response and processing times and throughput rates of a product or
system, when performing its functions, meet
requirements
Easiness of
adapting to
different
environments
*Including
conformance
to standards
Replaceability
Capacity
12
Code Quality
(ISO/IEC 25010)
Degree to which the maximum limits of a product or system parameter meet requirements
Efficiency
with regard
to processing
time
Efficiency
with regard to
resources
Security
Degree to which a
Confidentiality
product or system
protects information
and data so that persons
or other products or
systems have the
degree of data access
appropriate to their
types and levels of
authorization
Code Quality
(ISO/IEC 25010)
Degree to which a product or system ensures that Degree of cerdata are accessible only to those authorized to
tainty that data
have access
are accessible
only to those
authorized to
have access
Integrity
Nonrepudiation
Accountability
Authenticity
13
Quality
2.2
2.2
Rules
Overall Structure
In this guide, the basic matters to be followed when creating source code are organized as practices. For each practice, this guide introduces rules that are more specific reference information
to keep in mind at the time of coding.
These practices and rules provided in this guide are classified and arranged in order, according to their association to any of the four quality characteristics described earlier in 2.1. The following section defines what practice and rule actually mean in this guide (see also Figure 1):
Practice
A practice is a custom or a set of ideas on implementation to maintain source code quality. Each
practice reflects the basic concept of individual coding rule. These practices are broken down into
outline and details.
Rule
A rule is a specific agreement that must be followed and constitutes a part of coding convention.
This guide presents these rules as reference information. In this guide, a rule is also sometimes
used as a collective term that represents a group of relevant rules.
14
Reliability
Quality Concepts
Practices
in details
Efficiency
Language dependent
Rules:
Reference
information of
specific coding
rules that take
language
dependency into
consideration.
Portability
Language independent
(with the exception of some partially dependent)
Practices Overview
Practices:
Specific way of
thinking
constantly
applied in
implementation to
improve quality.
Maintainability
Added as
project-specific rule
15
16
When to Create
Create the coding convention before proceeding to the program design stage. While a coding
convention is a group of rules that are referred to during coding, some rules, such as, the naming
convention applied to function names are associated with program design, and therefore need to be
decided before starting the program design.
How to Create
Projects creating a new coding convention of their own are recommended to follow the procedure
described below, step by step:
Step-1 Decide on the policy for creating a coding convention.
Step-2 Choose the rules based on the creation policy that has been decided.
Step-3 Define the project-dependent parts of the rules.
Step-4 Determine the procedure for setting exceptions to the rules if necessary.
After following these steps in order, add any other rules as needed.
17
Step-2 Choose the rules based on the creation policy that has been decided
The next step is to choose the suitable rules from the Practices Chart in Part 2, based on the creation policy decided in Step-1. If the project decides on the policy that prioritizes on portability, for
example, efforts should be made to include many rules that address the portability issues in its coding convention.
In Part 2 - Coding Practices for Embedded Software of this guide, some rules are marked with
either or as a guide to facilitate the selection process. A rule marked with indicates that
it is regarded so important for the particular quality characteristic it addresses, that if this rule is not
adopted as a part of the coding convention, that quality aspect may be seriously impaired. Whereas,
indicates that it is a rule that is already so well-known among those who are very knowledgeable
about C language specifications that it may not necessarily be included in the coding convention.
The simplest way of creating a coding convention would therefore be to choose only the rules indicated with , which would result in a set of widely applied rules.
The rules treated either as type 2) or type 3) cannot be included in the coding convention as they
are. For rules treated as type 2) to be adopted as a part of the newly created coding convention, they
must be first chosen from the multiple alternatives presented in this guide. To adopt the rules treated
as type 3) as a part of the coding convention, they must be more fine-tuned so that they can address
the specific needs of each project. In doing so, the supplementary explanation provided to each practice described in this guide should serve as a useful reference on rule definition.
18
Be sure not to allow exceptions too easily. The substance of the rule will be lost when there
are too many exceptions.
The following is an example of the procedure for allowing exceptions.
[Example procedure]
E n h a n c i Existing
n g ex i s tCoding
i n g c o Conventions
d i n g c o nve n t i o n s
3.3
3.3Enhancing
For projects where coding conventions already exist, this guide can be a useful reference to review and enhance the contents of their coding conventions.
19
asmaterial
a Learning
Material
for sProgramLearning
for trand
for selftudy
3.4
3.4Serving
mers Training and Self-Study
This guide is a good learning material for programmers who have studied C language but are still
not used to or have little experience in practical coding.
Target Users
This guide is targeted at the following group of programmers:
- Programmers who have studied and acquired the basic skills in C language
- Programmers who have experience in other programming languages but are beginners in C
language
20
Part
Coding Practices
for Embedded Software:
Practices Chart
- How to Read the Practices Chart
- Terminology Used in the Practices Chart
- Coding Practices for Embedded Software
Reliability
Maintainability
Portability
Efficiency
How
H
owtotRead
o Rethe
a dPractices
t h e PrChart
a c t i c e s Ch a r t
Organizational Structure of the Practices
Coding practices shown in Part 2 are classified according to four software quality characteristics
(reliability, maintainability, portability, efficiency).
Practices in Outline
Practices closely related to each characteristic are largely divided into practices in outline.
For example, the practices closely related to maintainability are largely divided into five practices
in outline from Maintainability M1: Keep in mind that others will read the program to
Maintainability M5: Write in a style that makes testing easy.
Practices in Detail
Each practice in outline is broken down into more specific subsets called practices in detail. For
example, the practice in outline Maintainability M3: Write programs simply has four practices in
detail, which are:
Maintainability 3.1
Do structured programming.
Maintainability 3.2
Maintainability 3.3
Maintainability 3.4
22
Quality concept
Practice in outline
Reliability
R1.1.1
Various variables are used in programs written in C language. Without considering the
areas to be reserved in the computer and ensuring that these areas are already initialized by
the time these variables are used, unexpected malfunctions may occur.
Moreover, the pointers in C language need to be used carefully by being conscious of the
areas they point to. Since the misuse of pointers may cause serious problems to the entire
system, particular caution is necessary when using them.
Reliability 1 consists of the following three practices.
Reliability 1.1
Reliability 1.2
Reliability 1.3
Compliant example
void func() {
int var1 = 0; /* Initialize at the time of
declaration */
int i;
var1++;
/* Assign the initial value just before using
it */
for (i = 0; i < 10; i++) {
}
}
Preference guide
Reliability
Reliability
Practice in detail
Rule number Rule
Preference
guide
Rule
specication
Rule specification
Non-compliant example
void func() {
int var1;
var1++;
Compliant example
Non-compliant
example
If automatic variables are not initialized, their values become undened and the operation results may
differ depending on the environment. The initialization must be either at the time of declaration or just
before using the variable.
R1.1.2
Compliant example
Preference
guide
Remarks
Rule
specication
Non-compliant example
const int N;
const variables must be initialized at the time of declaration as values cannot be assigned to them subsequently. If not initialized, 0 will be assigned for external variables and the values are undened for automatic variables, which may cause unexpected behavior. Note that missing initialization at declaration
does not cause a compile error.
Note
30
Reliability1 R1 nitialize areas and use them in consid eration of their sizes.
31
Quality concept
Quality concepts are related to the main quality characteristics of ISO/IEC 25010. This guide
uses the following four quality concepts:
Reliability
Maintainability
Portability
Efficiency
Practice
Describes the practice to be followed by programmers during coding:
- In outline Defines the general concept of the practice. It is not dependent on programming
languages.
- In detail
Elaborates the general concept of the practice with more specific points that should
be noted. Like practices in outline, it is basically programming language-independent,
but some are stated as C language-specific.
Rule number
Identification number of each rule
23
Rules
Specific reference rule or rules for C language corresponding to the practice that must be
followed. The rules cited from MISRA C are written in the following format.
Examples: [MISRA C:2004 1.3], [MISRA C:2012 R8.14]
Preference guide
Provides supportive information (marks) to indicate whether the corresponding rule described
under eachpractice should be chosen as a part of the newly created coding convention or not.
No mark:
Rules considered to significantly impair the quality characteristics if they are not
followed.
Rule specification
Provides supportive information (verbal indicators) to indicate which rule need to be defined
more specifically in detail or not, depending on the project policy, or should be prescribed in
a document, such as, when it is recommended to record the behavior and usage of compilerdependent language specification as a document (the latter is referred to as the documentation
rule which can be used as it is, but is strongly recommended to be documented in more detail for
various reasons).
No mark:
Rules that do not need to be defined further in depth or prescribed in a documen with
more specific details
Choose:
Define:
Document:
24
Specific rules that need to be defined for each project. The part to be defined is
enclosed by
enclosed by
Compliant example
Example of source code written in compliance with the rule.
Non-compliant example
Example of source code violating the rule.
Remarks
Provides notes pertaining to C language specification, and explanation on why the particular rule
is necessary and what kind of problem(s) may be caused by violation of that rule, among others.
25
Terminology
in e
the
Chart
Ter
min o l oUsed
g y Us
d Practices
in th e Pr
ac tices
The meaning of the terms used in the chart is as respectively explained in the table below:
Term
Meaning
Access
Type specifier
Specifies a data type. There are two type specifiers, one that specifies basic
types such as char, int and float and the other that specifies types defined with
typedefs by the programmer for their own.
Type qualifier
Adds specific attributes to types. There are three type qualifiers: const, restrict
and volatile.
Storage class specifier Specifies the location where data are stored. There are four specifiers; auto,
register, static, and extern.
26
Boundary alignment
Indicates methods for the compiler to allocate data into memory. For example, if
int type is 2 bytes, be sure to allocate such data from an even address of the
memory and not to allocate from an odd address.
Trigraph sequence
Defined seguences of three characters such as ??=, ??/, ??(for the compiler
to replace with single character.
??=, ??/, ??( are interpreted into #, \ , [ respectively.
Lifetime
Duration that the references to a variable from the program is guaranteed after it
is generated.
Multibyte character
Null pointer
A pointer that is not equivalent to any pointers that point to data or functions.
Null character
Scope
The part of the program within which an identifier can be used to indicate, such
as, the variable it defines.
File scope refers to the scope up to the end of the file.
Side effect
Block
A range that is enclosed with braces {, } in data declarations and programs etc.
Enumeration type
Enumerator
Coding
Practices
for Embedded Software
This part presents coding practices for embedded software. As explained carlier, The coding
practices are categorized according to the perspective of four characteristics (quality concepts):
reliability, maintainability, portability and efficiency, which have been adopted from
the software quality characteristics defined in ISO/IEC 25010. Please note, however, that these
practices have been categorized in this way basically for the sake of convenience of the users of this
guide, and that there are actually some useful practices and corresponding rules that can be applied
to improve more than one characteristic (e.g.: both reliability and maintainability).
Moreover, the coding practices respectively related to these quality characteristics and the
reference rules that support the correct ways of executing these practices are also described in this
part of the guide.
Reliability
R Practices to improve the reliability of software that has been developed fall under this
category. Main points taken into consideration include:
Main points considered include:
- Minimizing problems arising while using the software;
- Increasing tolerability against bugs and interface violation.
Maintainability M Practices to create source code that is easy to modify and maintain fall under this category.
Main points taken into consideration include:
Maintainability
- Making the code easy to understand and modify;
- Minimizing the impact of modifications on the entire code;
- Making the modified code easy to check.
Portability
P Practices to port the software program that has been created on the assumption of being
Efficiency
E Practices to effectively utilize the performance and resources of the software that has been
27
Reliability
A large number of embedded software is incorporated into products and used to support our daily lives in various situations. Consequently, the level of reliability demanded to quite a number of
embedded software is extremely high. Software reliability requires
the software to be capable of not behaving wrongly (not causing
failure), not affecting the functionality of the entire software and
system in case of malfunction, and promptly restoring its normal
behavior after a malfunction occurs.
At the source code level, the point to be noted in regard to software reliability is the need of contriving methods to avoid coding
that may cause such malfunctions as much as possible.
Reliability
Reliability
Various variables are used in programs written in C language. Without considering the
areas to be reserved in the computer and ensuring that these areas are already initialized by
the time these variables are used, unexpected malfunctions may occur.
Moreover, the pointers in C language need to be used carefully by being conscious of the
areas they point to. Since the misuse of pointers may cause serious problems to the entire
system, particular caution is necessary when using them.
Reliability 1 consists of the following three practices.
Reliability 1.2
Reliability 1.3
Reliability 1.1
30
void func() {
int var1 = 0; /* Initialize at the time of
declaration */
int i;
var1++;
/* Assign the initial value just before using
it */
for (i = 0; i < 10; i++) {
}
}
Preference
guide
Rule
specification
Compliant example
Reliability
R1.1.1
Non-compliant example
void func() {
int var1;
var1++;
If automatic variables are not initialized, their values become undefined and the operation results may
differ depending on the environment. The initialization must be either at the time of declaration or just
before using the variable.
R1.1.2
Compliant example
Preference
guide
Rule
specification
Non-compliant example
const int N;
const variables must be initialized at the time of declaration as values cannot be assigned to them subsequently. If not initialized, 0 will be assigned for external variables and the values are undefined for automatic variables, which may cause unexpected behavior. Note that missing initialization at declaration
does not cause a compile error.
Note
Related rulesM1.11.1M1.11.3
Reliability1 R1 nitialize areas and use them in consid eration of their sizes.
31
Describeinitializations
initializationsexpressed
without excess
or deficiency.
R1.2 Describe
without
ex
Reliability
R1.2.1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Initializing an array with a string will not cause an error at declaration even if a space for a null character is not ensured in the array size. This is not a problem if described intentionally. However, when the
array is used as an argument for a string handling function etc., the absence of a null character indicating
the end of the string is more likely to cause unexpected behavior. When initializing a string, it is necessary to ensure a space for the null character at the end.
Related ruleM2.1.1
R1.2.2
Initialization of enumeration type (enum type) members shall be by either: not specifying any constants; specifying all the constants; or specifying
only the first member.
Compliant example
Preference
guide
Rule
specification
Non-compliant example
If an initial value is not specified to a member of an enumeration type, the value of the immediately
preceding member plus 1 (the value of the first member is 0) will be specified to this member. If some
initial values are specified while others are not, the same value may unintentionally be assigned to different members and may become the cause of unexpected behavior. To prevent the same value from
being assigned to different members, initialization of the members must be by either not specifying any
constants, specifying all the constants, or specifying only the first member, depending on the usage.
32
Rule
specification
Choose
Preference
guide
(1) Integer addition to or subtraction from (including ++ and --) pointers shall not be made; Array
format with [] shall be used for references and
assignments to the allocated area.
Reliability
R1.3.1
Compliant example
#define N 10
int data[N];
int *p;
int i;
p = data;
i = 1;
Compliant example of (1) and (2)
data[i] = 10;
/* conpliant */
data[i+3] = 20; /* conpliant */
Compliant example of (2)
*(p + 1) = 10;
(2) Integer addition to or subtraction from (including ++ and --) pointers shall be made only when the pointer points to the array and the
result must be pointing within the range of the array.
Non-compliant example
#define N 10
int data[N];
int *p;
p = data;
Non-compliant example of (1)
*(p + 1) = 10;
/* Non-compliant */
p += 2;
/* Non-compliant */
Non-compliant example of (2)
*(p + 20) = 10; /* Non-compliant */
Performing operations on pointers can blur the destinations pointed by the pointers. It raises the possibility of implanting bugs that is likely to refer or write to unsecured areas. Rather, using an array name
that points to the beginning of the area and to access elements of the array with indices will make the
program safer. A dynamic memory area obtained by malloc should be treated as an array, and a pointer
to the starting address of the area should be handled as the array name.
For multi-dimensional array, this rule applies to each partial array.
Regarding rule (2), it is permissible to point to the area directly after the last element of the array as long
as the array element is not accessed. In other words, in the case where int data[N] and p=data, p+N
complies with the rule as long as it is not used for accessing the array elements, whereas, using, such as,
*(p+N) that accesses an array element is non-compliant.
Reliability1 R1 nitialize areas and use them in consid eration of their sizes.
33
R1.3.2
Reliability
Compliant example
Preference
guide
Rule
specification
Non-compliant example
In C language, subtraction between pointers expresses how many elements exist between the two elements pointed by each pointer. In this case, if each pointer points to a different array, the way the variables are laid out between them is implementation-dependent and the execution result is not guaranteed.
This implies that subtraction between pointers is meaningful only when both pointers are pointing to
elements in the same array. Therefore, before subtracting one pointer from another pointer, the programmer must ensure that both pointers are addressing elements of the same array.
Related ruleR1.3.3
R1.3.3
Compliant example
#define N 10
char var1[N];
void func(int i, int j) {
if (&var1[i] < &var1[j]) {
Preference
guide
Rule
specification
Non-compliant example
#define N 10
char var1[N];
char var2[N];
void func(int i, int j) {
if (&var1[i] < &var2[j]) {
Comparing addresses of different variables does not cause a compile error, but is meaningless because
the address of the variable is implementation-dependent. In addition, the behavior of such a comparison
is not defined (undefined behavior).
Related rulesR1.3.2R2.7.3
34
Preference
guide
Reliability
R1.3.4
Rule
specification
Compliant example
Non-compliant example
By using restrict type qualifier, efficient code can be generated by a compiler and the accuracy of
static analysis by using such as the code checker will improve. However, the use of restrict type
qualifier will require the programmer to guarantee that the targeted areas will not overlap, and there is a
risk involved because the compiler will not output an error.
Reliability1 R1 nitialize areas and use them in consid eration of their sizes.
35
Reliability
Reliability
The data used in programs vary in how they are represented internally and in the range they
can be operated, depending on their types. When using these different types of data for operation, they must be written carefully by paying attention to various aspects, including precision
and size. Otherwise, unexpected malfunctions may occur when they are processed in, such
as, arithmetic operations. Therefore, there is a need to handle data with care, by taking their
ranges, sizes and internal representations, among others, into consideration.
2
1
36
Reliability 2.1
Reliability 2.2
Reliability 2.3
Reliability 2.4
Reliability 2.5
Reliability 2.6
Reliability 2.7
Reliability 2.8
R2.1 Make
comparisons that do not depend on internal representations.
representations.
Rule
specification
2
1
Compliant example
Preference
guide
R2.1.1
Reliability
2.1
Non-compliant example
In case of a floating-point type, values written in the source code do not exactly match with those actually implemented. Therefore, the comparison results must be judged by taking account of tolerance.
Related ruleR2.1.2
R2.1.2
Compliant example
void func() {
int i;
for (i = 0; i < 10; i++) {
Preference
guide
Rule
specification
Non-compliant example
void func() {
double d;
for (d = 0.0; d < 1.0; d += 0.1) {
If operations are repeatedly performed to a floating-point variable used as a loop counter, the
intended result may not be achieved due to accumulated calculation errors. Therefore, integer type (int type) should be used for loop counters.
Related ruleR2.1.1
37
R2.1.3
Reliability
Compliant example
2
1
struct TAG {
char c;
long l;
};
struct TAG var1, var2;
void func() {
if (var1.c == var2.c && var1.l == var2.l) {
Preference
guide
Rule
specification
Non-compliant example
struct TAG {
char c;
long l;
};
struct TAG var1, var2;
void func() {
if (memcmp(&var1, &var2, sizeof(var1)) == 0) {
Memories for structures and unions may contain unused areas. Since the values in the areas are unknown, memcmp should not be used. When making comparisons of structures or unions, they should be
made between the corresponding members.
Related ruleM1.6.2
R2.2.1
Compliant example
#define FALSE 0
/* func1 may return a value other than 0 and 1
*/
void func2() {
if (func1() != FALSE) {
- or if (func1()) {
38
Rule
specification
Non-compliant example
#define TRUE 1
/* func1 may return a value other than 0 and 1
*/
void func2() {
if (func1() == TRUE) {
Preference
guide
R2.3.1
Preference
guide
2.3
Reliability
R2.3 Use
the same data type to carry out operations or make
comparisons.
Rule
specification
2
1
Non-compliant example
Compliant example
Unsigned integer operations in C language wrap around without overflow (the result will be the remainder of the maximum representable value). Because the overflow is not flagged, there is a risk of
not noticing when the operation result differs from the intended result. For example, when there are two
environments that differ in the number of bits of int, the same constant expression produces different
operation results, depending on whether they exceed the representable value range or not.
R2.3.2
Compliant example
Preference
guide
Rule
specification
Non-compliant example
When writing code using different types, perform a cast to specify which type is expected as
the result.
Related ruleM1.4.1
39
R2.3.3
Reliability
Compliant example
2
1
Preference
guide
Rule
specification
Non-compliant example
Using comparison between variables with different ranges of representable values as a loop iteration
condition may produce unintended results and end up in an infinite loop.
R2.4
2.4
R2.4.1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
The type used in operation is determined by the type of the expression (operand) used for the operation,
and the type of the assignment destination is not taken into consideration at compile time. Therefore, do
not expect the operation to output its result in the type of the assignment destination if the operating type
differs from the destination type. When there is a need to execute an operation in the type that differs
from the operand type, perform a cast to convert the type of operand to the intended type before operation.
Related ruleR2.5.1
40
Preference
guide
When performing arithmetic operations or comparisons of expressions mixed with signed and
unsigned, an explicit cast to the expected type shall
be performed.
Reliability
R2.4.2
Rule
specification
Compliant example
Non-compliant example
long l;
unsigned int ui;
void func() {
l = l / ui;
if (l < ui) {
2
1
long l;
unsigned int ui;
void func() {
l = l / (long)ui;
- or l = (unsigned int)l / ui;
if (l < (long)ui) {
- or if ((unsigned int)l < ui) {
Some operations, such as, size comparison, multiplication and division output different results, depending on whether they are performed with signed or unsigned. If an operation is written for a mixture
of signedness, unsigned operation is not always executed because it is the compiler that determines
which type to execute the operation in (whether with signed or unsigned) by taking account of the
respective data sizes. Therefore, when performing an arithmetic operation of mixed signedness, there is
a need to check whether the intended operation is with signed or unsigned, and perform an explicit
cast to change the operating type to the desired type before operation so that the intended operation result can be expected.
Note: If there are data types that may have to be changed for use in intended operation, it is often
better to change them rather than performing a cast mechanically. Therefore, in such a situation,
first consider changing the data type.
41
R2.5.1
Reliability
2
1
Preference
guide
Rule
specification
/* Assignment examples */
short s;
/* 16 bits */
long l;
/* 32 bits */
void func() {
s = (short)l;
s = (short)(s + 1);
}
/* Operation examples */
unsigned int var1, var2; /* int size is 16
bits */
var1 = 0x8000;
var2 = 0x8000;
if ((long)var1 + var2 > 0xffff) { /* The
result is true */
Non-compliant example
/* Assignment examples */
short s;
/* 16 bits */
long l;
/* 32 bits */
void func() {
s = l;
s = s + 1;
}
/* Operation examples */
unsigned int var1, var2; /* int size is 16
bits */
var1 = 0x8000;
var2 = 0x8000;
if (var1 + var2 > 0xffff) { /* The result is
false*/
When a value is assigned to a variable that differs in type, the value may change (i.e. information may
be lost). The assignment destination, therefore, should be the same type whenever possible. When a
value is assigned to a different type intentionally in cases, such as, where there is no risk of information
loss or no impact even if information is lost, perform a cast to explicitly state the intention.
When performing an operation that outputs a result that exceeds the representable value range of the
type used, the result may become an unintended value. Therefore, for safety, carry out the operation
after verifying that the operation result is within the representable value range of the type used, or after
converting it to the type that could adequately accommodate larger values.
Note: In many cases, it is better to change data types used rather than casting mechanically.
Changing data types should be considered first.
Related ruleR2.4.1
42
Rule
specification
Compliant example
Non-compliant example
2
1
int i;
void func() {
i = -i;
Preference
guide
Reliability
R2.5.2
If a unary operator - is used in unsigned expression and the operation result falls out of representable value range of the original unsigned type, unintended behavior may occur.
For example, writing if ( - ui < 0 ) in the non-compliant example will not make this if
true.
R2.5.3
When ones complement (~) or left shift (<<) is applied to unsigned char or unsigned short type
data, an explicit cast to the type of the operation
result shall be performed.
Compliant example
uc = 0x0f;
if((unsigned char)(~uc) >= 0x0f)
Preference
guide
Rule
specification
Non-compliant example
uc = 0x0f;
if((~uc) >= 0x0f)/* It is not true */
The result of operation using unsigned char or unsigned short type will be signed int type.
When the sign bit turns on due to operation, the intended result may not be achieved. This is why casting to the type of the intended operation is necessary. The above non-compliant example shows that ~us
always becomes false as it produces a negative value.
Related ruleR2.5.4
43
R2.5.4
Reliability
Compliant example
2
1
unsigned char
a; /* 8 bits */
unsigned short b; /* 16 bits */
b = (unsigned short)a << 12; /* Clearly
indicated that the operation is 16 bits */
Preference
guide
Rule
specification
Non-compliant example
unsigned char
a; /* 8 bits */
unsigned short b; /* 16 bits */
b = a << 12; /* There may be an error in the
shift count */
The behavior of a shift operator whose right-hand side (shift count) specifies a negative value or a value
equal to or larger than the bit width* at the left-hand side (value to be shifted) is not defined in C language standard and will vary depending on the compiler used. (* This bit width will be that of int type
if the size is smaller than int .)
The intention of specifying a value up to the bit width of int type as the shift count will be unclear if
the left-hand side (value to be shifted) is of a type that is smaller in size, even though its behavior is defined in the language standard.
Related ruleR2.5.3
types
with which
data can the
be reprenseted.
R2.6 Use
Use
types
that the
cantarget
represent
target data.
R2.6.1
(1) The types used for bit field shall only be signed
int or unsigned int. If a bit field of 1 bit width is
required, unsigned int type shall be used, and
not the unsigned int type.
Preference
guide
Rule
specification
Choose
(2) The types used for bit field shall be signed int, unsigned int or
_Bool. If a bit field of 1 bit width is required, unsigned int type or
_Bool type shall be used.
(3) The types used for bit field shall be signed int, unsigned int, _
Bool, or those allowed by the compiler that are either enum or the
type that specifies signed or unsigned. If a bit field of 1 bit width
is required, the type that specifies unsigned or _Bool type shall
be used.
44
Non-compliant example
2
1
};
Reliability
Compliant example
45
(1) To be compatible with C90, use only the int type defined in C90, which is the int type that has
specified the signedness to either signed or unsigned. Do not use the signedness-unspecified int
type that may become signed or unsigned, depending on the compiler used.
Reliability
(2) Use only the int type that specifies the signedness as signed or unsigned defined in C99, or the
_Bool type, and do not use the int type that does not specify the signedness because the interpretation
of signedness or unsignedness may vary depending on the compiler used.
2
1
(3) In addition to the types defined in C99 language specification, the types defined in processing systems
can also be used. However, do not the integer type that does not specify the signedness, because the interpretation of signedness and unsignedness may vary depending on the compiler. Moreover, for the bitfield
of 1-bit integer type, specify unsigned because the values that can be expressed by 1-bit signed integer
type are only -1 and 0.
R2.6.2
Compliant example
Preference
guide
Rule
secification
Non-compliant example
The result of bitwise operation ( ~, << , >> , & , ^ , | ) to signed type may vary, depending on the compiler used.
46
Preference
guide
Rule
specification
Choose
2
1
R2.7.1
Reliability
R2.7
(2) Pointer type shall not be converted to other pointer type or integer
type with less data width than that of the pointer type, with the exception of mutual conversion between pointer to data type and
pointer to void* type.
(3) Pointer type shall not be converted to other pointer type or integer
type with less data width than that of the pointer type, with the exception of mutual conversion between pointer to data type and
pointer to other data type, and between pointer to data type
and pointer to void* type.
Compliant example
int
int
char
int
void
*ip;
(*fp)(void) ;
*cp;
i;
*vp;
Non-compliant example
int
int
char
char
*ip;
(*fp)(void) ;
c;
*cp;
47
If a pointer type variable is casted or assigned to another pointer type, it is difficult to identify what
kind of data is contained in the area the pointer points to. With some MPUs, runtime errors occur if the
destination of a pointer that is not at word boundaries is accessed as int type; thus changing pointer
types may cause a risk of unexpected bugs. It is safer not to cast or assign pointer type variables to
other pointer types. Converting pointer types to integral types is also risky, involving the same problem
stated above. Such conversions, therefore, should be reviewed with experts, whenever deemed necessary. Moreover, attention must also be given to the value ranges of int type and pointer type. Be sure
to check the specifications of the compiler beforehand, because there may be cases where the size of the
pointer type is 64 bits even though the size of int type is 32 bits.
sstdint.h defines intptr_t and uintptr_t, which respectively represents signed and unsigned
integral types with data width capable of holding a value converted from a pointer type and be converted
back to that type with a value that equals to the original pointer. These types should be used when converting between pointer type and integrer type.
Reliability
2
1
48
Details (1)
Reliability
Conerted to
Other type
Details (2)
2
1
Conerted to
Integrer type
Pointer to P o i n t e r
Pointer to
W i t h l e s s d a t a With more data
function t o v o i d
data type
width than that of width that than of
type
type
the pointer type the pointer type
Details (3)
Converted to
49
R2.7.2
Reliability
Preference
guide
Rule
specification
Compliant example
2
1
Non-compliant example
Be careful when accessing the areas qualified by const or volatile, because they are only for reference and must not be optimized. If a cast that removes any const or volatile qualification from the
type addressed by a pointer is performed, the compiler will not be able to check and detect error descriptions in the program even if there are any, or may perform an unintended optimization.
R2.7.3
Compliant example
Preference
guide
Rule
specification
Non-compliant example
int * func1() {
return -1;
}
int func2() {
}
return 0;
}
50
Non-compliant example
int func(void) ;
int func();
Compliant example
Preference
guide
Rule
specification
2
1
R2.8.1
Reliability
R2.8
The declaration int func() does not mean that a function has no parameters. It is an old-styled (K&R
style) declaration that means that a function has unknown number and types of parameter. Therefore,
when declaring functions with no parameters, write void explicitly.
Related ruleR2.8.3
R2.8.2
Preference
guide
Rule
specification
Compliant example
Non-compliant example
Choose
Document
Without understanding the behavior of functions with a variable number of arguments in the processing
system, their use may cause stack overflow or other unexpected results.
In addition, when the number of arguments is variable, the number and the types of the arguments are
not explicitly specified, and it will lower readability of the code.
MISRA C:2012 prohibits the use of functions defined in stdarg.h.
Related ruleR2.8.3
51
R2.8.3
Reliability
Preference
guide
Rule
specification
Compliant example
2
1
Non-compliant example
*/
This rule is for preventing the prototype declaration and function definition from becoming inconsistent.
Related rulesR2.8.1R2.8.2
52
Reliability
Reliability
Reliability 3.1
Reliability 3.2
Reliability 3.3
Reliability 3.4
Reliability 3.5
Reliability 3.6
3
1
It is essential to be thorough with describing how to handle all the potential errors, by also
taking account of unexpected events that may occur in cases that are even conceived as highly
unlikely from the standpoint of program specifications. Moreover, writing code in ways that
do not rely on language specifications, such as, explicit indication of operator precedence can
also improve safety. To achieve high reliability, it is desirable to make every effort to avoid
coding that leads to malfunction and write in a way that ensures intended behavior and safety
as much as possible.
53
R3.1.1
Reliability
3
1
guide
of elements shall always be specified.
Rule
(2) In an extern declaration of an array, the number specification Choose
of elements shall always be specified, except for
extern declarations of arrays that correspond to
the array definition that includes initialization and has omitted the
number of elements.
Compliant example
Non-compliant example
int var1[MAX];
int var1[MAX];
Making an extern declaration without specifying the size of an array will not cause an error. However, if
the size is not specified, it may cause problems in checking outside the array range. Therefore, it is better to explicitly specify the array size in its declaration. However, there are cases where it is better not to
specify the array size in the declaration, such as, when the size of the array is determined by the number
of initial values and is not fixed in the declaration.
Related ruleR3.1.2
54
Iteration conditions for a loop to sequentially access array elements shall include the decision to
whether the access is within the range of the array
or not.
Reliability
R3.1.2
Preference
guide
Rule
specification
Non-compliant example
char var1[MAX];
for (i = 0; var1[i] != 0; i++) {/* If 0s are
not set in the var1 array, there is a risk
of accessing outside the array range */
3
1
Compliant example
char var1[MAX];
for (i = 0; i < MAX && var1[i] != 0; i++) {
/* Even if 0s are not set in the var1 array,
there is no risk of accessing outside the
array range */
R3.1.3
Compliant example
Non-compliant example
int a[ 5 ] = { [ 0 ] = 1 };
int b[ ] = { [ 0 ] = 1 };
Preference
guide
Rule
specification
Unless the size of the array is clearly indicated when defining the array, the largest index among the elements that will be initialized will be determined as the size. When a designated iinitializer is used, there
are times when it is not clear which index is the largest and should be initialized.
Related ruleR3.1.1
55
R3.1.4
Reliability
Preference
guide
Compliant example
3
1
#define MAX
1024
void func(void) {
int a[MAX]; /* Compliant Secured an array of
largest length */
Rule
specification
Non-compliant example
void func(int
int a[n];
n) {
/* Non-compliant Variable
length array */
The use of variable length array type has the following problems:
Risk of stack overflow
Variable length array can be assigned to a stack area. Therefore, if the variable length array size is big,
there is a risk of stack overflow.
Behavior that is not defined in C language standard
The behavior when the variable length array size is not a positive value is not defined in C language
standard.
Misconceived array size
int y = 10;
typedef
int
INTARRAY[y];
y = 20;
INTARRAY z; /* Array size of z is 10, and not 20. */
56
Compliant example
if (y != 0)
ans = x/y;
Preference
guide
Rule
specification
3
1
R3.2.1
Reliability
R3.2
Non-compliant example
ans = x/y;
Apart from when the value is obviously not 0, the operations should be performed after checking that
the right-hand side expression of division or remainder is not 0. Otherwise, division by zero error may
occur at runtime.
Related rulesR3.2.2R3.3.1
R3.2.2
Compliant example
if (p != NULL)
*p = 1;
Preference
guide
Rule
Specification
specification
Non-compliant example
*p = 1;
Related rulesR3.2.1R3.3.1
57
Reliability
R3.3
R3.3.1
3
1
If a function returns error information, then that error information shall be tested.MISRA C:2012 D4.7
Compliant example
Non-compliant example
p = malloc(BUFFERSIZE);
if (p == NULL)
/* Error handling */
else
*p = '\0';
p = malloc(BUFFERSIZE);
*p = '\0';
Preference
guide
Rule
specification
When a function returns a value, the code that does not use that return value may cause an error. If it is
not necessary to reference the return value, consider setting a project-specific rule to clearly indicate the
unnecessity of referencing, such as, by casting to void.
Related rulesR3.2.1, R3.2.2, R3.5.1 R3.5.2
58
Non-compliant example
Rule
specification
3
1
Compliant example
Preference
guide
Reliability
R3.3.2
Whether the constraints on parameters are checked by the function that calls or the function that is called
depends on how the interface is designed. However, in order to prevent checking from being overlooked, the same check should be performed in one place. Therefore, the check should be performed by
the function that is called.
In case the function that is called cannot be changed, such as, when it is in a library, create a wrapper
function.
Example of wrapper function:
int func_with_check(int arg) {
/* If arg is violating the parameter constraints, return range_error */
/* If not, call func and return the result */
}
/* Use a wrapper function to make the function call */
if (func_with_check(para) == range_error) {
/* Error processing */
}
C99 allows the specification of the lower limit of array size by using a static qualifier in an array declaration of a formal parameter. For example, in the following function declaration, the lower limit of elements of an argument of array a is specified as 3.
void func(int a[static 3]);
By specifying such constraints on parameters, tools like the compiler would quite likely check the restrictions applied to arguments.
59
R3.4
Reliability
R3.4.1
3
1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Since the stack size used at runtime for recursive calls cannot be predicted, there is a risk of stack overflow.
60
R3.5.1
Reliability
R3.5
Compliant example
} else {
/* Write an exception handling process */
if (var1 == 0) {
} else {
/* NOT REACHED */
}
3
1
guide
if-else if statement. If it is known that the else
Rule
condition does not normally occur, the description specification Define
of the else caluse shall be either one of the following:
(i) An exception handling process shall be written in the else clause.
(ii) A comment specified by the project shall be written in the else
clause.
Non-compliant example
If there is no else clause in an if-else if statement, it is not clear whether the programmer has forgotten to write the else clause or deliberately left out the else clause be cause the else condition dose
not occur. Even if it is known that the else condition does not normally occur, the behavior of the program when an unexpected condition occurs can be specified by writing the else clause as follows:
(i) Write the behavior under unexpected conditions in the else condition (How program behaves
in case of occurrence of the else condition should be determined.)
Or, the program is much easier to understand by just writing a comment that the else condition does
not occur.
(ii) Write a comment specified by the project such as /* NOT REACHED */ clearly indicating that the
else condition does not occur to express that the else clause has not been forgotten.
Related rulesR3.3.1R3.5.2
61
R3.5.2
Reliability
3
1
Compliant example
break;
case 1:
break;
default:
/* Write an exception handling process */
break;
}
switch(var1) {
case 0:
break;
case 1:
break;
default:
/* NOT REACHED */
break;
}
62
Preference
Non-compliant example
break;
case 1:
break;
}
If there is no default clause in a switch statement, it is not clear whether the programmer has forgotten to write the default clause or deliberately left out the default clause because the default
condition does not occur. Even if it is known that the default condition does not normally occur, the
behavior of the program when an unexpected condition occurs can be specified by writing the default
clause as follows:
(i) Write the behavior under unexpected conditions in the default condition (Predefine the behavior of
theprogram if by any chance the default condition occurs).
Or, the program is much easier to understand by just writing a comment that the default condition
does not occur.
(ii) Write a comment like /* NOT REACHED */ that clearly indicates that the default condition does
not occur to express that the default clause was not written because it was forgotten. Such comment will improve the readability of the program.
Reliability
3
1
Related rulesR3.3.1R3.5.1M3.1.4
R3.5.3
Compliant example
void func() {
int i;
for (i = 0; i < 9; i += 2) {
Preference
guide
Rule
specification
Non-compliant example
void func() {
int i;
for (i = 0; i != 9; i += 2) {
If the amount of change for the loop counter is not 1, an infinite loop may occur. Therefore, for comparison to determine the number of loop iterations, do not use the equality operators (==) or the inequality
operator (!=)
63
R3.6
Reliability
R3.6.1
Variables whose values are changed in an expression shall not be referred to or modified in the
same expression.
3
1
Compliant example
f (x, x);
x++;
- or f (x + 1, x);
x++;
Preference
guide
Rule
specification
Non-compliant example
f (x, x++);
Compilers do not guarantee the execution (evaluation) order of each actual argument in functions with
multiple parameters. The arguments may be executed from the right or from the left. In addition, compilers do not guarantee the execution order of the left-hand and the right-hand side of binary operations
such as + operation. Therefore, if the same object is updated and referenced in a sequence of arguments
or binary operation expressions, the execution result is not guaranteed. Such a problem, where the execution result is not guaranteed, is called a side effect problem. Do not write code that causes such side
effect problems.
This rule, however, does not prohibit descriptions, such as, those shown below which do not cause the
side effect problem.
x = x + 1;
x = f(x);
Related rulesR3.6.2M1.8.1
64
Preference
guide
Function calls with side effects and volatile variables shall not be described more than once in a
sequence of actual arguments or binary operation
expressions.
Reliability
R3.6.2
Rule
specification
Compliant example
2.
volatile int v;
y = v;
f(y, v);
Non-compliant example
1.
extern int G_a;
x = func1() + func2();
int func1(void) {
G_a += 10;
}
int func2(void) {
G_a -= 10;
3
1
1.
extern int G_a;
x = func1();
x += func2();
int func1(void) {
G_a += 10;
}
int func2(void) {
G_a -= 10;
2.
volatile int v;
f(v, v);
Compilers do not guarantee the execution (evaluation) order of each actual argument for functions with
multiple parameters. The arguments may be executed from the right or flom the left. In addition, compilers do not guarantee the execution order of the left-hand and the right-hand side of binary operations
such as + operation. Therefore, the execution results of two or more function calls with side effects and
volatile variables in a sequence of arguments or binary operation expressions may not be guaranteed.
Such unsafe descriptions must be avoided.
Related rulesR3.6.1M1.8.1
65
R3.6.3
Reliability
Preference
guide
Rule
specification
Compliant example
3
1
x = sizeof(i);
i++;
y = sizeof(int[i]);
i++;
Non-compliant example
x = sizeof(i++);
y = sizeof(int[i++]);
Until C90, the expression in parenthesis of sizeof operator was used only for finding the size of the
expression type, and was not executed.
Therefore, even when ++ operator like sizeof(i++) was described, i was not incremented. However,
in C99, if the type is a variable length array, there are cases when the expression is evaluated. In those
cases, i in sizeof(int[i++]) will be incremented by ++ operator. Such description should not be used
because it can easily be misunderstood.
66
Maintainability
Many embedded software developments require maintenance tasks, including the modification of the software that
has already been developed.
There are various reasons for maintenance. For example,
maintenance becomes necessary:
When a bug is found in one part of the released software
and must be modified;
When a new function is added to existing software in reWhen any kind of additional work is carried out on the
already developed software as in the above examples, it
is important to perform such work as accurately and efficiently as possible to maintain the quality of the software.
This is called maintainability in the field of system development.
This section clarifies the practices to keep and improve the
maintainability of embedded software source code.
Maintainability 1: Keep in mind that others will read the
program.
Maintainability
2:
Write
in a style that can prevent
modification errors.
Maintainability 3: Write programs simply.
Maintainability 4: Write in a unified style.
Maintainability 5: Write in a style that makes testing
easy.
Maintainability
It is easily conceivable that source code is reused and maintained by engineers who are not
the original creators. Therefore, it is necessary to write source code that is easy to understand
by taking account of others who will read it later.
Maintaiability 1.1
Maintaiability 1.2
Maintaiability 1.3
Maintaiability 1.4
Maintaiability 1.5
Maintaiability 1.6
Maintaiability 1.7
Maintaiability 1.8
Maintaiability 1.9
Maintaiability 1.10
Maintaiability 1.11
Maintaiability 1.12
Maintainability
1
68
M1.1
M1.1.1
Compliant example
void func(void) {
Preference
guide
Rule
specification
Non-compliant example
Maintainability
Declarations (definitions) of unused functions, variables, parameters labels, etc. impairs maintainability
because it makes it difficult to determine whether the programmer has forgotten to delete them or has
made a description error.
However, when writing a call back function, make it explicit that parameter is not used, by not describing the name of the parameter to keep the function types consistent.
Related rules M1.9.1M4.7.2
M1.1.2
Compliant example
#if
0
/* Ineffective due to ~ */
a++;
#endif
Preference
guide
Rule
specification
Non-compliant example
/* a++; */
69
Invalidated sections of the code, as a principle, should not be left in the code, because they make the
code difficult to read
However, when there is a need to invalidate certain sections of the code, predefine a rule to explicitly
indicate the invalid code sections, such as, by enclosing the invalid sections with #if 0, instead of commenting them out.
Related rulesM1.12.1M4.7.2
Maintainability
M1.2.1
Compliant example
Choose
Non-compliant example
If the declaration is int *p;, the type of p is int*. However, if the declaration is int *p, q;, the type
of q becomes int instead of int*.
Related ruleM1.6.1
70
Compliant example
Preference
guide
Rule
specification
Non-compliant example
float f;
long int l;
unsigned int ui;
f = f + 1.0F;
f = f + 1.0;
func(1l); /* 1l (el) can be confused with 11 */
if (ui < 0x8000) {
Maintainability
float f;
long int l;
unsigned int ui;
M1.2.2
Basically, when there is no suffix, an integer constant will be an int type and a floating constant will be
a double type. However, when an integer constant value that cannot be expressed with an int type is
described, its type will be the one that can express that value. Therefore, 0x8000 will be unsigned int
if int is 16 bits, and signed int if int is 32 bits. If you would like to use it as unsigned, it is necessary to explicitly describe U as the suffix. In addition, in case of a target system where the operation
speed differs between floating point number of float type and that of double type, when performing
operations between a float type variable and a floating constant without a suffix F, constant, it should
be noted that the operation will be a double type.
For floating constants, writing at least one digit on both sides of the decimal point will make them easily
recognizable as floating constants.
Related rule M1.8.5
M1.2.3
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Long strings that extend to multiple lines will become easier to read by describing them as concatenation of multiple string literals.
71
M1.3.1
Maintainability
Compliant example
Non-compliant example
if (i_var1 == 0) {
i_var2 = 0;
} else {
i_var2 = 1;
}
switch (i_var1 == 0) {
case 0:
i_var2 = 1;
break;
default:
i_var2 = 0;
break;
}
Preference
guide
Rule
specification
When an expression evaluating to true or false is used in a switch statement, the number of branch
directions will be two, and the necessity of using the switch statement as a multiway branch command
becomes low. Compared to if statements, switch statements have a higher possibility of errors, such as,
writing the default clause wrongly or missing break statements. Therefore, it is recommended to use if
statements unless the number of branch directions is three or more.
M1.3.2
The case labels and default label in a switch statement shall be described only in the compound statement (excluding nested compound statements) within the body of the switch statement.
Compliant example
switch (x) {
case 1:
{
break;
case 2:
break;
default:
break;
}
72
Preference
guide
Rule
specification
Non-compliant example
break;
default:
break;
}
M1.3.3
Compliant example
Preference
guide
Rule
specification
Non-compliant example
extern global;
int func(void) {
func(void) {
If data types are not described in definitions and declarations of functions or variables, they are interpreted as int type. Explicitly specifying data types improves readability. In C99 language standard,
these descriptions that do not explicitly specify the data types are prohibited and will be detected as error
by the compiler.
Maintainability
M1.4.1
Compliant example
if
if
if
if
Non-compliant example
The objective of this rule is to write an expression that prevents confusion in understanding the order of
precedence of each operand in && or ||. Its aim is to highlight the operation of each operand in && or ||
to improve the readability by enclosing the expression that contains an operator other than unary, postfix
and cast operators with ( ) . Another rule that may be considered is to enclose ! operation with ( ) because the order of precedence may be confusing to beginners.
[Related rulesR2.3.2M1.5.2
73
M1.4.2
Compliant example
a = (b << 1) + c;
- or a = b << (1 + c);
Preference
guide
Rule
specification
Define
Non-compliant example
Operator precedence in C language is difficult to capture. Therefore, set a rule as exemplified below to
improve its readability. If an expression contains multiple binary operators that differs in the order of
operation priority, parentheses () shall be used to explicitly indicate the operator precedence, provided
that the parentheses () may be omitted in four arithmetic operations.
To learn more about the operator precedence and its interpretation, refer to MISRA C:2012 Rule 12.1
(p.103).
Maintainability
[Related ruleM1.5.1
M1.5.1
void func(void);
void (*fp)(void) = &func;
if (func()) {
Preference
guide
Rule
specification
Non-compliant example
void func(void);
void (*fp)(void) = func; /* Non-compliant:
There is no & */
if (func) {
/* Non-compliant: Address is
obtained rather than calling the
function. It might be mistakenly
written as afunction call without
arguments. */
In C language, if a function name is written alone, it means obtaining the function address, and not calling the function. This means that, for obtaining the function address, there is no need of placing & in
front of the function name. However, the function name without a preceding &, in some cases, may be
misunderstood that it is for a function call (for example, when using languages like Ada and Ruby that
write only the name to call a subprogram without arguments). By following the rule to add & when obtaining the function address, it will become easier to detect mistakes in function names written as they
are without & and subsequent () .
[Related ruleM1.4.2
74
Compliant example
Preference
guide
Rule
specification
Non-compliant example
int x = 5;
int x = 5;
if (x != 0) {
if (x) {
Maintainability
M1.5.2
In conditional expressions, when the result of the expression is zero (0), it is treated as false, and nonzero is treated as true. Therefore, comparative operations may be omitted in conditional expressions.
However, such description may cause unintended behavior. For this reason, the comparisons should not
be omitted to make the intention of the program explicit. Moreover,since bool, true and false are
defined as macros in stdbool.h, any of them should be used to describe a type that represents true or
false, or a constant that represents a true or false value.
[Related rulesR2.2.1M1.4.1
Use one
area for one purpose.
M1.6
1
1.6
M1.6.1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
75
Reusing variables should be avoided as it impairs readability and increases the risk of causing errors
during modification.
[Related ruleM1.2.1
M1.6.2
Preference
guide
Rule
specification
Choose
Maintainability
Compliant example
int i;
if (s_var.type == INT) {
s_var.u_var.i_var = 1;
}
i = s_var.u_var.i_var;
Non-compliant example
int i;
if (s_var.type == INT) {
s_var.u_var.c_var[0] = 0;
s_var.u_var.c_var[1] = 0;
s_var.u_var.c_var[2] = 0;
s_var.u_var.c_var[3] = 1;
}
i = s_var.u_var.i_var;
Union allows the same memory space to be declared with areas of different sizes. However, since the
way bits of data overlap among members is implementation-dependent, unexpected behavior may occur.
Therefore, if union is going to be used, follow rule (2) as a precautionary measure.
[Related ruleR2.1.3
76
M1.7
1.7
M1.7.1
Preference
guide
Rule
specification
Maintainability
Compliant example
int var1;
void func(int arg1) {
int var2;
var2 = arg1;
{
int var3;
var3 = var2;
}
}
Non-compliant example
int var1;
void func(int arg1) {
int var1;
/* The same name of a variable
outside the function is used
*/
var1 = arg1;
{
int var1;/* The same name of a variable
in the outer scope is used */
var1 = 0;/* Intention of which var1 is
assigned is unclear */
}
}
The program will become easier to read by using unique names within the program, except for cases like
automatic variables where the scope is limited.
In C language, in addition to the scope defined by file and block, names have the following four name
spaces that vary according to the category they belong to:
1. Label 2.Tag3. Member of structure or union 4. Other identifiers
*Macro has no name space.
The language specification allows using the same name to different identifiers if their name spaces differ, but this rule restricts such usage for the purpose of improving the readability of the program.
77
As the exception of rule 2., the typedef name may be the same as the name of the structure member,
union member or tag related to that typedef. As the exception of rule 3., the tag name may be the same
as the name of the typedef related to that tag.
[Related ruleM4.3.1
M1.7.2
Maintainability
Compliant example
#include <string.h>
void *my_memcpy(void *arg1, const void *arg2,
size_t size) {
Preference
guide
Rule
specification
Non-compliant example
#undef NULL
#define NULL
((void *)0)
#include <string.h>
void *memcpy(void *arg1, const void *arg2, size_
t size) {
Redefining names for functions, variables and macros defined in the standard library degrades the readability of the program.
[Related ruleM1.8.2
78
M1.7.3
Compliant example
Preference
guide
Rule
specification
Non-compliant example
int _Max1;
int __max2;
int _max3;
/* Reserved */
/* Reserved */
/* Reserved */
struct S {
int _mem1; /* Not reserved, but shall not be
used */
};
Maintainability
[Related ruleM1.8.2
79
M1.8
1.8
M1.8.1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Maintainability
The right-hand side of && or || operators may not be executed, depending on the result of the condition of their left-hand side. Take, for example, an expression with a side effect of incrementing. It this
expression is written on the right-hand side, whether the increment is executed or not will be difficult to
understand, because it depends on the condition of the left-hand side. Therefore, expressions with side
effects shall not be described on the right-hand side of && or || operators.
[Related rulesR3.6.1, R3.6.2
M1.8.2
Compliant example
#define
#define
START 0x0410
STOP 0x0401
Preference
guide
Rule
specification
Non-compliant example
#define
#define
#define
#define
BIGIN {
END
}
LOOP_STAT for(;;) {
LOOP_END }
Macro definitions can be leveraged to make the code look like it is written in a language other than C, or
greatly reduce the amount of code. However, using macros for these purposes will degrade readability.
It is important to use macros only where coding and modification errors can be avoided. For do-whilezero, see MISRA C:2004.
[Related ruleM1.7.2
80
M1.8.3
Preference
guide
Rule
specification
#line serves as the means to intentionally modify file names or line numbers of warning or error messages output from the compiler. It is provided under the assumption that code is generated by tools, and
is not intended to be used directly by the programmers.
s = "abc?(x)";
Non-compliant example
s = "abc??(x)";
Non-compliant example
Compliant example
Rule
specification
Compliant example
Preference
guide
Maintainability
M1.8.4
C language standard defines trigraph sequences and alternative tokens, assuming that there may be cases
where some characters cannot be used for coding, depending on the environment used for development.
The following nine three-character patterns, known as trigraph sequences:
??= ??( ??/ ??) ?? ??< ??! ??> ??can be replaced respectively at the beginning of preprocessing with the following corresponding singlecharacter counterparts:
#
[
\
]
^
{
|
}
~
The following two-character patterns, known as digraph sequences:
<% %> <: :> %: %:%:
are handled respectively as equivalent to
{
}
[
]
#
##
in the lexical analysis.
C99 defines the following macros in the header <iso646.h>
and and_eq bitand bitor compl
not not_eq or or_eq xor xor_eq
as alternative spellings that correspond respectively to the following tokens.
&& &= & ~ ! !=
= ^ ^=
Since trigraph sequences and alternative tokens are not frequently used, many compilers support them as
an optional feature.
81
M1.8.5
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Maintainability
Constants starting with zero (0) are interpreted as octal. No zero (0) can be added in front of decimal
numbers to align their digits for the purpose of appearance (i.e.: zero padding is not allowed).
[Related ruleM1.2.2
M1.9
1.9
state its intention.
M1.9.1
Compliant example
for (;;) {
/* Waiting for interruption */
}
#define NO_STATEMENT
i = COUNT;
while ((--i) > 0) {
NO_STATEMENT;
}
[Related ruleM1.1.1
82
Non-compliant example
for (;;) {
}
i = COUNT;
while ((--i) > 0);
Preference
guide
Rule
specification
M1.9.2
Preference
guide
Rule
specification
Define
Define the unified style of writing infinite loops, for example, by selecting from one of the following:
Write the infinite loops uniformly as for(;;); .
Write the infinite loops uniformly as while(1); .
Use the macro defined for the infinite loop.
Maintainability
M1.10
1.10
M1.10.1
Compliant example
#define MAXCNT 8
if (cnt == MAXCNT) {
Preference
guide
Rule
specification
Non-compliant example
if (cnt == 8) {
By defining a constant as a macro, its meaning can be stated explicitly. When modifying a program
where the same constant is used in multiple places, modification errors can be prevented much more
easily if this same constant is defined as a macro, because then, there will only be a need to modify one
macro.
For data size, however, use sizeof instead of using a macro.
[Related ruleM2.2.4
83
M1.11.1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Maintainability
int read_only_mem;
/* Read-only memory */
int constant_data = 10; /* Read-only data that
does not require memory
allocation */
/* Only reads the contents pointed by arg */
void func(char *arg, int n) {
int
i;
for (i = 0; i < n; i++) {
put(*arg++);
}
}
When a variable is only referenced and not modified, declaring it as const-qualified variable makes
it clear that it is not modified.That is why read-only variables should be const-qualified. Moreover, a
memory that is only referenced by the program but modified by other execution units should be declared
with const volatile qualification so that the compiler can check and prevent the program from renewing it by mistake. Furthermore, function interfaces can be clearly stated by adding consts to parameters when the memory spaces indicated by the parameters are only referenced in function processing.
[Related ruleR1.1.2
84
Compliant example
Preference
guide
Rule
specification
Non-compliant example
volatile int x = 1;
while (x == 0) {
/* x is not modified within the loop and is
modified by other execution units */
}
int x = 1;
while (x == 0) {
/* x is not modified within the loop and is
modified by other execution units */
}
Maintainability
M1.11.2
Areas qualified as volatile prohibit the compiler from optimizing them. Prohibition of optimization
means that executable object is generated strictly to every description, including even those considered
logically as unnecessary of processing. Suppose there is a description x; that has no meaning logically
except for only referencing variable x. If it is not qualified as volatile , the compiler will normally ignore such statement and will not generate an executable object. Whereas, if it is qualified as volatile
, the compiler will generate an executable object that only references variable x (loads it to the register).
This description can be assumed to have meaning in indicating the interface to IO registers (mapped to
the memory) that are reset when the memory is read. Embedded software has IO registers for controlling
hardware that should be qualified as volatile when considered appropriate, based on their characteristics.
Compliant example
M1.11.3
Preference
guide
Rule
specification
Define
Non-compliant example
/* Allocate to ROM */
int x = 100;
Variables qualified as const can be allocated to ROMization target areas. For example, when developing
a program where ROMization is applied, qualify the read-only variables as const , and specify the name
of the section to which these variables are allocated by, such as, #pragma.
[Related ruleR1.1.2
85
M1.12.1
Maintainability
#if 0
/* */
#endif
#if 0
/*
#endif
#if 0
#else
int var;
#endif
#if 0
#else1
int var;
#endif
#if 0
/* I don't know */
#endif
#if 0
I don't know
#endif
2
1
[Related ruleM1.1.2
86
Preference
guide
Rule
specification
are
Maintainability
One of the patterns that allows bugs to slip into a program easily is when other bugs are
created by mistake while fixing detected bugs. Especially if it has been a while since the
source code was written or if an engineer other than the creator modifies the source code,
unexpected misunderstanding may occur.
Efforts to reduce such modification errors as much as possible are strongly desired.
Maintainability 2.2
Maintainability
Maintaiability 2.1
1
2
87
M2.1
2.1
Clarify
the grouping of structured data and blocks.
M2.1.1
Preference
guide
Rule
specification
Maintainability
Compliant example
Non-compliant example
In initialization of arrays and structures, at least a pair of braces { } is required, but in this case, it is
difficult to see how the data for initialization are assigned. It is safer to create blocks according to the
structure, and fully describe the data for initialization without omitting any.
2
1
M2.1.2
The body of if, else if, else, while, do, for, and
switch statements shall be enclosed into blocks.
Compliant example
Non-compliant example
if (x == 1) {
func();
}
if (x == 1)
func();
Preference
guide
Rule
specification
If there is only one statement that is controlled by, such as, an if statement, there is no need to enclose
this statement into a block. However, when the program is modified and this single statement is changed
into multiple statements, there is a possibility of forgetting to enclose these multiple statements into a
block. To prevent such modification errors, enclose the body of each controlled statement into a block.
88
Rule
specification
Non-compliant example
}
void func2(void) {
y = 0;
/* Initialize each time */
Maintainability
Compliant example
1
2
void func1(void)
{
static int x = 0;
if (x != 0) { /* Refer to the value in the
immediately preceding call */
x++;
}
}
void func2(void)
{
int y = 0;
/* Initialize each time */
Preference
guide
M2.2.1
To declare variables in functions, it is sometimes effective to declare them with static storage class
specifiers. The following positive effects can be expected if static is specified:
Static memory space is reserved and the space is valid until the end of the program (Without static,
generally, stack memory is used and is valid until the end of the function.)
Initialization occurs only once after the program is started and if a function is called more than once,
the value assigned in the previous call is retained.
Therefore, among the variables accessed only within a function, the variables with values that are retained even after the function terminates should be declared with static storage class specifiers.
In addition, declaring a large memory space for an automatic variable may cause stack overflow. When
there is such risk, one preventive measure is to use static to reserve static memory space even if the
values do not need to be retained after the function terminates. However, when using static for such
purpose, its intention should be explicitly stated by, such as, comments (to prevent potential misunderstanding that static has been used by mistake).
[Related ruleM2.2.2
89
M2.2.2
Compliant example
x = 0;
}
void func2(void) {
if (x == 0) {
x++;
}
Preference
guide
Rule
specification
Non-compliant example
Maintainability
x = 0;
}
void func2(void) {
if (x==0) {
x++;
}
2
1
The fewer the global variables, the higher the readability of the entire program becomes. To prevent the
number of global variables from increasing, static storage class specifiers should be used as much as
possible.
[Related rulesM2.2.1M2.2.3
M2.2.3
Compliant example
}
void func2(void) {
func1();
90
Preference
guide
Rule
specification
Non-compliant example
}
void func2(void) {
func1();
The fewer the global functions, the higher the readability of the entire program becomes. To prevent the
number of global functions from increasing, static storage class specifiers should be used as much as
possible.
[Related ruleM2.2.2
Rule
specification
Maintainability
Non-compliant example
#define
ENGLAND 0
#define
FRANCE
1
#define
SUNDAY
0
#define
MONDAY
1
int
country, day;
if ( country == ENGLAND ) {
if ( day == MONDAY ) {
if ( country == SUNDAY ) { /* It is impossible
to check by tools */
Compliant example
1
2
enum ecountry {
ENGLAND, FRANCE,
} country;
enum eweek {
SUNDAY, MONDAY,
} day;
if ( country == ENGLAND ) {
if ( day == MONDAY ) {
if ( country == SUNDAY ) { /* It is possible
to check by tools */
Preference
guide
M2.2.4
To define the constants that are related like a set, use the enumeration type. By defining related constants
as enum type, and using this type, mistakes caused by the use of incorrect values can be prevented.
While macro names defined by #define are expanded at the preprocessing stage and the compiler does
not process those names, enum constants defined by enum declaration will be the names processed by
the compiler. The names processed by the compiler are easier to debug, becouse they can be referenced
during symbolic debugging.
[Related rulesM1.10.1 P1.3.2
91
Maintainability
From the standpoint of software maintainability, there is no better software than those
created from simply written programs.
C language enables the structuring of software by, such as, dividing the program into
separate source files and functions. Structured programming that represents program
structure through three forms: sequence, selection and repetition, is also one of the applicable
techniques to write simple software programs. Writing simple software descriptions through
effective use of software structuring is strongly desired. Moreover, particular attention should
also be given to writing styles applied to describe, such as, iteration processing, assignment
and operations, as some may make the program difficult to maintain.
Maintainability
3
1
92
Maintaiability 3.1
Do structured programming.
Maintaiability 3.2
Maintaiability 3.3
Maintaiability 3.4
Do structured programming.
M3.1
3.1
For any iteration statement, there shall be at most
one break statement used for loop termination.
MISRA C:2012 R15.4
Rule
specification
Non-compliant example
Maintainability
Compliant example
3
1
end = 0;
for (i=0; loop iteration condition && !end; i++)
{
Iterated processing 1;
if (termination condition1 || termination
condition2) {
end = 1;
} else {
Iterated processing 2;
}
}
-orfor (i=0; loop iteration condition; i++) {
Iterated processing 1;
if (termination condition1 || termination
condition2) {
break;
}
Iterated processing 2;
}
Preference
guide
M3.1.1
This rule is to prevent the program logic from becoming complex. If a flag has to be prepared only for
eliminating the break statement, sometimes it is better not to prepare the flag and to use a break statement. (Be careful, however, when using an end flag like in the case shown above as compliant example,
because it may complicate the program.)
93
M3.1.2
Compliant example
Maintainability
ERR_RET:
end_proc();
return err;
}
Preference
guide
Rule
specification
Choose
Non-compliant example
3
1
These rules are to prevent the program logic from becoming complex. The purpose is not to eliminate
all the goto statements. The important point is to eliminate unnecessary goto statements to prevent the
program from becoming complicated (i.e., not being able to read it straightforwardly from top to bottom). In some cases, the readability can actually be improved by writing goto statements. Therefore,
when programming, keep in mind how simply the logic can be expressed.
For example, goto statement can be useful to make the program simple, such as, when it is used to
jump to error processing or exit from multiple loops.
94
M3.1.4
Preference
guide
Rule
specification
Choose
Define
3
1
Non-compliant example
Maintainability
Compliant example
One of the typical examples of coding error is caused by forgetting to write the break statement in a
switch statement in C language. To prevent it, avoid writing a case statement without the break statement unnecessarily. If the code is intended to continue processing to the next case without the break
statement, always insert a comment to explicitly indicate that the absence of the break statement is not
a problem. Define what kind of comment to insert in such case in the coding convention. As one example, /* FALL THROUGH */ is a comment that is frequently used.
[Related ruleR3.5.2
95
M3.1.5
Preference
guide
Rule
specification
Choose
This rule is to prevent the program logic from becoming complex. When a program has many entry or
exit points, they will not only complicate the program but will also make it difficult to set break points
during debugging. In C language, there is only one entry point for a function but the exit points are
where the return statements are written.
Maintainability
M3.2
3.2
3
1
M3.2.1
Compliant example
j--;
}
Preference
guide
Rule
specification
Choose
Non-compliant example
In general, the use of comma expressions make the program complicated. However, the progam may
sometimes become easier to understand in expressions for initializing and updating in for statements by
using comma expressions to collectively describe all the pre-loop operations as one set and all the loopend operations as another set.
[Related ruleM3.3.1
96
M3.2.2
Compliant example
x = y = 0;
Preference
guide
Rule
specification
Non-compliant example
y = (x += 1) + 2;
y = (a++) + (b++);
Assignments include the compound assignments (+= -=, etc) beside the simple assignment (=). Multiple
assignments may be written in one statement, but since they impair readability, one statement should
contain only one assignment.
However, commonly used conventional descriptions shown below do not impair readability in many
cases. They may be treated as exceptions of this rule.
c = *p++;
*p++ = *q++;
Maintainability
3
1
M3.3
3.3
M3.3.1
Compliant example
j++;
}
Preference
guide
Rule
specification
Non-compliant example
In MISRA C:2012, rules 13.5 and 13.6 in MISRA C:2004 have been consolidated into R14.2, which
states that a for loop shall be well-formed. According to this rule, the first clause of a for statement,
for example, shall either be empty, assign a value in the loop counter or define and initialize the loop
counter (C99).
[Related rulesM3.2.1M3.3.2
97
M3.3.2
Compliant example
Preference
guide
Rule
specification
Non-compliant example
i++;
}
See M3.3.1.
Maintainability
[Related ruleM3.3.1
3
1
M3.3.3
Compliant example
}
Compliant example of (1)
c = *p++;
while (c != '0') {
c = *p++;
}
Rule
specification
Choose
Non-compliant example
}
Non-compliant example of (1)
while (c = *p++) {
}
/* Since this is an expression used
conventionally, it is compliant to (2).
(However, be careful of its usage, because its
readability depends on the programmers coding
skills.) */
98
Preference
guide
( expression )?:,
Non-compliant example
int ***p;
typedef char **strptr_t;
strptr_t *q;
Rule
specification
Maintainability
Compliant example
int **p;
typedef char **strptr_t;
strptr_t q;
Preference
guide
M3.4.1
Since it is difficult to understand the changes in the pointer values in three or more levels, multiple
pointer indirections impair maintainability.
1
4
99
Maintainability
Recently, developing programs under the shared efforts of multiple programmers has become a
widely accepted approach in software projects. If these programmers apply different coding styles
to write their assigned portion of the source code, the reviewers or other programmers may later
face difficulty checking what each programmer has written. Moreover, if the naming of variables,
information to be described in a file, and the order to describe the information, among others, are
not uniform, unexpected misunderstanding or errors may arise from such inconsistencies. This is
why writing the source code as much as possible according to a unified coding style in a single
project or within the organization is often said to be desirable.
Maintainability
4
1
100
Maintaiability 4.1
Maintaiability 4.2
Maintaiability 4.3
Maintaiability 4.4
Maintaiability 4.5
Maintaiability 4.6
Maintaiability 4.7
M4.1.1
Preference
guide
Rule
specification
Define
To make the code easier to read, it is important to unify the coding style applied in the project.
When defining a new style convention to be followed in the project, the recommended approach would
be to select from already existing coding styles. Existing coding styles have been developed from various schools, and many programmers create their programs based on any one or more of these preestablished styles. One of the benefits of selecting from these existing coding styles is that the format
can be easily specified by the format commands available in editors and other tools. If no coding style is
clearly specified in the existing project, the recommendation would be to define a coding convention that
matches most closely with the current source code.
What is most important in deciding on the style convention is not in deciding what kind of style to define, but is in defining a unified style to be followed.
Explained below are the set of style-related items to be defined:
Maintainability
1
4
1Position of braces { }
Unify the position to place the braces { } so that the beginning and end of a block will become easier
to read (see Representative styles).
2Indentation
Indentation makes a group of declarations and operations easier to read. For unified use of indentation,
define the following:
Whether to use spaces or tabs for indentation;
If spaces are used, how many space characters are set for one indent? If tabs are used, how many
characters are set for each tab?
3How to use spacing
Spacing makes the code easier to read. For example, define the following rules:
Add a space before and after binary and ternary operators, except for the following operators.
[ ], ->, . (period), , (comma operator)
Do not add a space between unary operator and its operand.
By applying these rules, coding errors that are attributable to compound assignment operators will become easier to detect.
101
[Examples]
x=-1;
x =- 1;
Besides those stated above, the following rules are also defined in some cases:
Add a space after a comma (except for commas for parameters in macro definitions)
Add a space before the left parenthesis enclosing control statements such as, if and for. Do not
add a space before the left parenthesis of a function call. This rule makes it easier to identify
function calls. This rule makes it easier to identify function calls.
4Position to place a new line character for line continuation
When an expression becomes lengthy and extends beyond the length of an easily readable line, a new
line character shall be placed at an appropriate position. In placing a new line character, the recommended approach is to apply either one of the following two methods. What is important is to write the
continuation line after indenting.
Maintainability
4
1
x = var1
var5
if (var1
var3
Representative styles
1K&R style
This is a coding style used in The C Programming Language (widely known as K&R).K&R used as
the acronym of this book derives from the initials of the two authors. In the K&R style, the braces { }
and indentation are placed in the positions described below:
Position of braces: Place the braces { } for function definitions at the beginning of a new
line. Place the braces { } for others (including structures and control
statements, such as, if, for and while) on the same line without continuing
to a new line (see Example of K&R style).
1 tab. In the first edition of The C Programming Language, the width
Indentation:
of a tab was set to 5 spaces, but in the second edition (ANSI compliant),
the number of spaces is set to 4.
102
2BSD style
This is a description style adopted by Eric Allman who wrote many BSD utilities. It is also called the
Allman style. In the BSD style, the braces { } and indentation are placed in the positions described
below:
Position of braces: Start all the function definitions, if , for and while , etc, from a new line
and place the braces { } at the column aligned with the beginning of the
previous line (see Example of BSD style).
enerally defined as 8 spaces, but 4 is also common.
Indentation: G
3GNU style
Maintainability
This is a coding style for writing GNU packages. It is defined in GNU Coding Standards written by
Richard Stallman and volunteers in the GNU project. In the GNU style, the braces { } and indentation
are placed in the positions described below:
Position of braces: Start all the function definitions, if , for and while , etc, from a new
line. Place the braces { } for function definitions at column 0, and braces
{ } for others after indenting 2 spaces (see Example of GNU style).
Indentation: 2 spaces. Indent 2 spaces for both the braces { } and their body.
1
4
103
Unify the style of writing comments.
M4.2
M4.2.1
Preference
guide
Rule
specification
Define
Writing good comments makes the program easier to read. To improve the readability further, a unified
style of writing is necessary.
There are document generation tools that create documents for maintenance and examination from
the source code. When utilizing such tools, they can be most effectively used by writing in a style that
conforms to their specifications. In general, when the explanation of the variables and functions are
described according to certain comment conventions, the document generation tools enable these descriptions to be extracted from the source code and reflected in the generated documents. Therefore, it is
important to examine the specifications of these tools and define the comment conventions accordingly.
Presented below are some established styles of writing comments that have been extracted from existing
coding conventions and related literature.
Maintainability
4
1
/* Write a comment.
* Write a comment.
*/
Position of comments
Should be tabbed over to the same tab setting as the code that they describe.
- End-of-line comments
Start them apart from the statement by using the tab. If there are more than one of such
comments, align them all to the same tab setting.
2GNU coding standards
The following comment rules are described in the GNU Coding Standards:
Language English.
104
Maintainability
Position
Other practices
1
4
105
M4.3
4.3
M4.3.1
Maintainability
Preference
guide
Rule
specification
Define
Preference
guide
Rule
specification
Define
See M4.3.2.
[Related rulesM1.7.1, M1.7.2, M1.7.3, P1.1.2, P1.2.1
4
1
M4.3.2
Readability of programs is greatly affected by naming. There are various methods for naming but important points are to be consistent and to make the names easy to understand.
For naming, the following items shall be defined:
Guidelines for names in general
How to name files (including folders and directories)
How to name globally and locally
How to name macros, etc.
Presented in the following are some naming guidelines and rules introduced in existing coding conventions and related literature. They are useful as reference when creating a project-specific naming convention newly. If no naming convention is explicitly defined in the existing project, the recommendation
would be to create a naming convention that is closest to the current source code.
Typical naming conventions
106
enum constants should either have the initial character or all the characters capitalized.
It is best to avoid names that differ only in case, like foo and Foo.
Global names should have a common prefix identifying the module that they belong with.
A file name should be eight characters or less (excluding the extension), starting with an alphabetic
character and followed by alphanumeric characters.
File names that are the same as library header filenames should be avoided.
Names with leading and trailing underscores should not be used.
Avoid names that differ only in case.
Example: foo and Foo
Maintainability
Overall
Nothing in particular
Macro names should be in all CAPS.
Example: #define MACRO
enum constants are Capitalized or in all CAPS.
Other
1
4
Dont choose terse namesinstead, look for names that give useful information about the meaning
of the variable or function. Names should be English.
Use underscores to separate words in a name.
Stick to lower case; reserve upper case for macros and enum constants, and for name-prefixes that
follow a uniform convention.
Use underscores to separate words in a name.
Example: get_name
Stick to lower case; reserve upper case for macros and enum constants,
and name-prefixes that follows a uniform convention.
Overall
Dont choose terse namesinstead, look for names that give useful information about the meaning of the variable and function.
Names should be English.
Nothing in particular
Reserve upper case for macros.
Example: #define MACRO
Reserve upper case for enum constants.
107
Overall
Other
4Others
Identifiers will not differ by:
- The presence/absence of the underscore character
- The interchange of the letter O, with the digit 0 or the letter D
- The interchange of the letter I, with the letter l (el) or the digit 1
- The interchange of the letter S with the digit 5
- The interchange of the letter Z with the digit 2
- The interchange of the letter n with the letter h.
Maintainability
4
1
Hungarian notation:
How to name files:
T
here is a notation called Hungarian notation that explicitly indicates the
type of variable.
Give a name with a prefix, for example, that expresses the subsystem.
108
M4.4
4.4
M4.4.1
The descriptive contents of header files (declarations, definitions, etc) and the order they are described in shall be defined.
Preference
guide
Rule
specification
Define
Items commonly used in a program shall be described in header files to prevent the risk of modification
errors when they are scattered in different places. Header files should contain macro definitions, tag declarations for structures, unions and enumeration types, typedef declarations, external variable declarations and function prototype declarations that are commonly used in multiple source files.
For example, they should be described in the following order:
Maintainability
4 #define macros
6 typedef definitions (type definitions for basic types such as int or char)
1
4
109
M4.4.2
The descriptive contents of source files (declarations, definitions, etc) and the order they are described in shall be defined.
Preference
guide
Rule
specification
Define
In a source file, definitions of variables and functions, definitions or declarations of macros, tags, and
types (typedef types) used only in the individual source file should be described.
For example, they should be described in the following order:
11Variable definitions
12Function definitions
Maintainability
4
1
110
To use or define external variables or functions (except for functions used only in the file), the header
file describing their declarations shall be included.
Compliant example
Rule
specification
Non-compliant example
Maintainability
-------------#include "my_inc.h"
int x;
int func(int in)
{
Preference
guide
M4.4.3
In C language, variables must either be declared or defined before being used. On the other hand, functions can be used without declarations or definitions. However, to ensure that declarations and definitions are consistent, the declarations should be described in the header file, and that header file should be
included.
x;
Compliant example
int
Preference
guide
1
4
M4.4.4
Rule
specification
Non-compliant example
int
int
x;
x;
Definitions without initialization for external variables can be described more than once. However, the
behavior is not guaranteed when an external variable is initialized in multiple files.
111
M4.4.5
Compliant example
Preference
guide
Rule
specification
Non-compliant example
/* Variable declaration */
/* Function declaration */
Maintainability
Header files might be included into several source files. Therfore, describing variable definitions and
function definitions in a header file may unnecessarily enlarge object code size generated after compilation. Basically, only declarations or type definitions should be described in a header file.
4
1
M4.4.6
Header files shall be descriptively capable of handling redundant inclusions.The descriptive method
to achieve this capability shall be defined.
Compliant example
Preference
guide
Rule
specification
Define
Non-compliant example
The descriptive contents of header files should be organized to avoid redundant inclusions. However,
there are cases when redundant inclusions become unavoidable. To prepare for such cases, header files
should be written in such a way that will make them possible of handling multiple inclusions.
As an example, the following may be defined as the rule for writing header files that are capable of handling redundant inclusions:
Example of the rule:
#ifndef macro that judges whether the header has already been included or not shall be written at the
beginning of the header file, so that the descriptions that follow will not be compiled in subsequent inclusions. In this case, the macro name should be the same as the header file name but replacing all the
lowercase letters to uppercase letters, and the period . to underscore _ .
112
M4.5.1
1In a function prototype declaration, all the parameters shall not be named (types only.)
2In a function prototype declaration, all the pa-
Preference
guide
Rule
specification
Choose
{
}
/* The parameter
name differs from
the name in the
prototype
declaration */
1
4
Non-compliant example
Maintainability
Compliant example
In a function prototype declaration, parameter names can be omitted, but describing appropriate parameter names is useful as function interface information. When describing parameter names, use the same
name as in the definition to avoid unnecessary confusion. As for the parameter type name, making it
literally the same as the function definition is also recommended to make the code easier to read.
Moreover, if the parameter is an array of specific size, it is desirable to specify the number of its elements.
Example: void func(int a[4]) {}
[Related ruleM1.4.1
113
M4.5.2
Compliant example
struct TAG{
int mem1;
int mem2;
};
struct TAG x;
M4.5.3
Preference
guide
Rule
specification
Non-compliant example
struct TAG{
int mem1;
int mem2;
} x;
Maintainability
Preference
guide
Rule
specification
Choose
, shall not be placed before the last } in the list of initial value
2
expressions for structures, unions and arrays, nor in the list of
enumerators. However, placing , before the last } in the list of
initial values for array initialization is allowed.
4
1
Compliant example
Non-compliant example
The usage of comma in descriptions for initializing multiple data is generally divided into two schools of
coding rules. One school follows the tradition of not placing a comma after the last initial value in order
to indicate the end of initialization explicitly. Another school follows the tradition of placing a comma at
the end by considering the easiness of adding or deleting initial values. Decide on which rule to follow
by weighing the importance of the usage of comma for such descriptions in your specific cases.
In C90 standard, it was not acceptable to have , just before } that indicates the end of an enumerator list, but this became acceptable in C99 standard.
[Related ruleM2.1.1
114
Rule
specification
Define
Non-compliant example
p = NULL;
dat[0] = NULL;
p = NULL;
dat[0] = 0;
p = 0;
dat[0] = NULL;
p = 0;
dat[0] = 0;
1
4
Maintainability
Compliant example
Preference
guide
M4.6.1
NULL has been conventionally used to express the null pointer, but the expression of the null pointer varies, depending on the execution environment. For this reason, some people think that it is safer to use 0.
115
M4.7.1
Compliant example
Non-compliant example
Preference
guide
Rule
specification
Maintainability
If the body and parameters of a macro are not enclosed with parentheses ( ) , there is a risk of bug being produced when the operations are not performed in the expected order, since the operation order
depends on the order of precedence of operators that come next to the macro after expanding the macro
and the operators in the macro.
4
1
M4.7.2
Preference
guide
Rule
specification
Define
Compliant example
Non-compliant example
#ifdef AAA
/* Process when AAA is defined */
#else
/* not AAA */
/* Process when AAA is not defined */
#endif
/* end AAA */
#ifdef AAA
/* Process when AAA is defined */
#else
/* Process when AAA is not defined */
#endif
If #else or #endif is described in a distant location or nested in a partitioned process by macros, such
as, #ifdef , their correspondence becomes difficult to understand. Therefore, add a project-defined
comment to #else or #endif that corresponds with, such as, #ifdef to make their correspondence
easier to understand.
[Related rulesM1.1.1M1.1.2
116
Compliant example
Rule
specification
Non-compliant example
#if AAA
#endif
- or #defined DD(x) defined(x)
#if DD(AAA)
#endif
Maintainability
#if defined(AAA)
#endif
- or #if defined AAA
#endif
Preference
guide
M4.7.3
#if macro name does not determine whether a macro is defined or not. For example, when #if AAA
is written, it will be evaluated as false not only when macro AAA is not defined, but also when the
value of macro AAA is 0. The C language standard does not define how to process defined operator.
Therefore, to check whether a macro is defined or not, defined operator should be used.
defined operator should not be described other than by defined(macro_name ) or defined macro_
name , because they are the only two ways of describing defined that are supported in C language
standard, and any other descriptions of defined may cause an error or may be interpreted differently,
depending on the compiler used.
5
1
[Related ruleM4.7.7
M4.7.5
Compliant example
#define
AAA
#define
BBB
#define
CCC
struct stag {
int
mem1;
char *mem2;
};
0
1
2
Preference
guide
Rule
specification
Non-compliant example
117
In general, macro definitions (#define) are all described together at the beginning of the file. If they are
scattered in various parts of the file, for example, by describing them in blocks, they will become difficult to read. Moreover, cancellation of definitions (#undef ) within a block will also degrade the readability. Also note that, unlike the scope of variables, macro definitions are valid only up to the end of the
file. The description below shows how the program in the above non-compliant example can be rewritten to make it compliant:
enum etag { AAA, BBB, CCC };
struct stag {
enum etag
mem1;
char
*mem2;
};
[Related ruleM4.7.6
Maintainability
M4.7.6
Preference
guide
Rule
specification
1
5
#undef can change the state of #defined macro name to undefined. But the use of #undef involves
the risk of degrading the readability, because the interpretation of #undef may differ, depending on
where the macro name is referred to.
[Related ruleM4.7.5
118
Rule
specification
Non-compliant example
#define ABC 2
#if ABC
Maintainability
Compliant example
#define TRUE 1
#define FALSE 0
#if TRUE
#if defined(AAA)
#if VERSION == 2
Preference
guide
M4.7.7
5
1
In case of #if or #elif controlling expression, true or false is evaluated by the controlling expression. Therefore, the controlling expression should be described in a way that would make it easy to
evaluate true or false, thus making the program easy to read.
[Related ruleM4.7.3
119
Maintainability
One of the essential tasks in embedded software development is to check the behaviors
(through testing). However, with recent complex embedded software, it is becoming
increasingly challenging to fulfill this task when faced with difficulties caused by, such as,
bugs and malfunctions detected during tests that cannot be reproduced. Therefore, when
writing the source code, it is desirable to be more conscious of writing in a style that will
make the root cause analysis easy to perform when problem arises. Moreover, particular
attention must also be given to descriptions that involve, such as, the use of dynamic
memory, by keeping in mind the risk of memory leak, among other points of concern.
Maintainability
1
5
120
Maintaiability 5.1
Maintaiability 5.2
M5.1
causes of problems when they occur.
5.1
M5.1.1
The rules for writing the code for setting debug options and for recording logs in release modules shall
be defined.
Preference
guide
Rule
specification
Define
Besides implementing the specified functionalities correctly, a good program requires coding that also
takes account of the easiness to debug and investigate into the causes of problems when they occur. Descriptions that make investigation of problems easy to conduct can be achieved by writing descriptions
for debugging that are not reflected in the release modules and descriptions for outputting logs after release that are reflected in the release modules. Explained below are the points to take into consideration
when determining the rules to be followed in writing each of these descriptions.
Maintainability
5
1
Descriptions for debugging, including print statements used during program development, need to be
written as isolated descriptions that are not reflected in the release module. Explained below are two
ways of writing the descriptions for debugging: (a) by isolating the debug descriptions using macro definitions; and (b) by using assert macros for debugging purpose.
(a) Using macro definitions to isolate debug descriptions
Use the macro definitions to identify the code parts to be compiled so that the debug descriptions are not
reflected in the provided release module. Strings, such as, DEBUG and MODULEA_DEBUG that contain
DEBUG as part of the name are commonly used as those macro names.
Example of rule definition:
#ifdef DEBUG shall be used to isolate the debug code. (DEBUG macro shall be specified at compile
time.)
[Code example]
#ifdef DEBUG
fprintf(stderr, "var1 = %d/n", var1);
#endif
#ifdef DEBUG shall be used to isolate the debug code. (DEBUG macro shall be specified at compile
time). In addition, the following macro shall be used to output debug information.
DEBUG_PRINT(str);
121
Since this macro is defined in the common header of the project, debug_macros.h , this header shall
be
included when using this macro.
-- debug_macros.h -#ifdef DEBUG
#define DEBUG_PRINT(str)
#else
#define DEBUG_PRINT(str)
#endif /* DEBUG */
fputs(str, stderr)
((void) 0)
/* no action */
[Code example]
void func(void) {
DEBUG_PRINT(">> func\n");
DEBUG_PRINT("<< func\n");
}
Maintainability
In C language standard, assert macro is provided as a macro for program diagnosis. It is useful for
making coding errors easier to detect during debugging. To facilitate debugging, define where to use the
assert macro and follow this defined usage throughout the project. By doing so, it will be possible to
collect consistent debug information during, such as, the integration test, and such information, as a result, will help make debugging easier.
The following is a brief explanation on how to use the assert macro, using a coding example that
shows how this macro is used in a function definition written under the precondition that the null pointer
is never passed as the argument.
1
5
If the NDEBUG macro is defined at compile time, the assert macro does nothing. On the other hand, if
the NDEBUG macro is not defined and the expression passed to the assert macro is false, the program
abends after outputting the file name and the line number of the source to the standard error. Note that
the macro name is NDEBUG, not DEBUG.
assert macro is a macro provided by the compiler in assert.h . By using the following example as
a reference, examine how to abort the program and determine whether to use the macro provided by the
compiler or to provide your own assert function.
#ifdef NDEBUG
#define
assert(exp)
((void) 0)
#else
#define
assert(exp)
(void) ((exp)) || (_assert(#exp, __FILE__, __LINE__)))
#endif
void _assert(char *mes, char *fname, unsigned int lno) {
fprintf(stderr, "Assert:%s:%s(%d)n", mes, fname, lno);
fflush(stderr);
abort();
}
122
C11 allows the offset of struct member and string constant size to be checked at compile time by writing static assert that can be evaluated at compile time in the source code.
_Static_assert( sizeof(t) <= 4, "The size of t is exceeding 4 bytes.");
Maintainability
Logs should be output not only when an abnormal condition is detected, but also at the timing of,
such as, data communication with an external system. The point is to output logs at appropriate
timing (such as, when key events occur) that will make it easier to trace the history and faster to
identify the root cause of the detected abnormality.
5
1
Information on the process executed immediately before the occurrence of the abnormal condition,
the data values processed at that time, and information for tracing memory usage are some of the
log information that should be recorded to enhance the traceability of the history and facilitate the
investigation of the cause of the abnormality.
Macro or function for outputting log information
Localize the log information output as a macro or a function. It is often preferable to make the
log output destination changeable.
M5.1.2
Compliant example
Preference
guide
Rule
specification
Choose
Non-compliant example
The evaluation order of # operator and ## operator is not defined. Therefore, # and ## operators should
not be mixed, nor used twice or more.
123
M5.1.3
Compliant example
Preference
guide
Rule
specification
Non-compliant example
Using functions rather than function-like macros facilitates tracking processes by stopping at the beginning of a function during debugging etc.
In addition, the compiler performs type checking with the functions and helps to detect coding mistakes.
The functions can be inline functions. For more information about the performance of inline functions
and object code size, see E1.1.1.
Maintainability
1
5
M5.2.1
Preference
guide
Rule
specification
Choose
Define
Using dynamic memory involves the risk of accessing invalid memory as well as the risk of memory
leak that leads to depletion of system resources, which may be caused by forgetting to return the obtained memory space to the system.
Some compilers provide functions for debug shown below. First, check the compiler used. Open source
software also has pieces of source code for debug and they are useful as references when creating your
own.
Example of rule definition:
To obtain and return dynamic memories, do not use standard functions such as malloc or free, but X_
MALLOC and X_FREE functions provided by the project should be used. Code for debug should be created by compiling the source with -DDEBUG option.
124
p = X_MALLOC(sizeof(*p) * NUM);
if (p == NULL) {
return (MEM_NOTHING);
}
X_FREE(p);
return (Compliant);
Maintainability
Described below are problems that tend to occur when dynamic memory is used.
Buffer overflow
5
1
This occurs as a result of referencing or updating areas beyond the range of obtained memory. In
particular, when an area outside the range is accidentally updated, this failure does not occur at the
time of update but will occur when the memory destroyed by the update is referenced. The problem
with dynamic memory is that it is very difficult to locate which part of the memory has been destroyed.
Forgetting to initialize
When a class area is allocated with new and an appropriate constructor is defined, there is no risk
of initialization being forgotten. However, be careful when an area other than class is allocated with
new, because initialization will not be performed automatically.
Memory leak
There is a risk of this problem being caused by forgetting to return the obtained memory space.
This problem does not occur with programs that terminate each time after running once. However,
with programs that keep running, memory leak can occur and become the cause of memory depletion and system malfunction.
Use after return
When the obtained memory space is returned due to, such as, delete, the returned memory space
may be reused later, such as, when new is called. In case the deleted memory address is used to
update the memory, the memory space will be destroyed if it is already being reused for other purpose. As explained in the case with buffer overflow, it is very difficult to locate which part of the
memory has been destroyed.
125
The code that leads to these problems does not cause a compile error. In addition, problems do not occur
at the location where the bugs were implanted, making them undetectable in tests that are just for checking the normal specifications. They cannot be discovered unless the code is carefully reviewed or tests
are performed after inserting a test code specifically written to detect such problems or after adding a
special library to the program for similar purpose.
Maintainability
1
5
126
Portability
One of the distinctive aspects of embedded software is that
there are diverse options in the platform used for software operation. This also means that there are many possible combinations of MPU options and OS options to select the hardware and
software platforms from. As the number of functionalities realized by the embedded software increases, opportunities to port
the existing software to other platforms by modifying or remodeling it to make it compatible with multiple platforms are also on
the rise.
Due to this trend, software portability is becoming an extremely
important element also at the source code level. In particular,
writing in a style that is implementation-dependent is one of the
most common mistakes made on a regular basis.
Portability
Portability 1.1
Portability 1.2
Portability 1.3
Confirm and document data type representations, behavioral specifications of advanced functionalities and implementation-dependent parts.
Portability 1.4
For source file inclusion, confirm the implementationdependent parts and write in a style that is not implementation-dependent.
Portability 1.5
Portability
1
128
P1.1.1
fea-
Preference
guide
Rule
Choose
specification Document
At present, while C99 is the widely used C language standard, the latest version is C11. In addition, there
are still many compilers that also support the older version, C90.
One way of thinking would be to choose rule (2) and allow the use of functionalities defined in the latest
language standard, C11, that are specifically supported by the compiler used.
Regarding the acceptable ways of using the functionalities that are not specified in the language standard, the details are provided in the following related rules.
Related rules P1.1.3P1.2.1P1.2.2P1.3.2P2.1.1P2.1.2
Preference
guide
Portability
P1.1.2
Rule
Document
specification
Portability1 P1 Write in a compiler independent way.
In the language standard, there are implementation-defined items whose behavior varies depending on
the compiler used. For example, the following are implementation-defined and should be documented if
they are used.
How to represent floating-point numbers
For C90, how to handle signs of remainders for integer division
The search order of files for the #include directive
#pragma
129
P1.1.3
Preference
guide
Rule
Document
specification
Define
The C language standard does not define the interface for making programs written in other languages
available from a C language program. In other words, using a program written in another language requires the use of an advanced functionality, which means that portability will be impaired. Therefore,
when using such a program, document the specifications of the compiler used and define its usage, regardless of the possibility of porting.
Related rulesP1.1.1P2.1.1
P1.2
fined in the language standard.
1.2
P1.2.1
Portability
Preference
guide
Rule
specification
Define
The basic character set defined in the language standard as usable for source code are upper and lower
case letters of the Latin alphabet, decimal digits, graphic characters ( _ { } [ ] # ( ) < > % : ;
. ? * + / ^ &
= , ), space character, and control characters that represent the horizontal tab, vertical tap and form feed.
International characters and multibyte characters (like Japanese) can be used as identifiers and characters, but they may not be supported by some compilers. Therefore, if these characters are going to be
used, check beforehand that they can be used in the following locations and define their usage.
Identifier
Comments
String literals
- Processing when \ exists in the character codes of the string (whether special care is required or
whether options are required at compile time etc.)
- The necessity to write using wide string literals (with the prefix L such as Lstring .)
130
Character constants
- The bit length of the character constant
- The necessity to write using wide character constants (with the prefix L such as L ).
The file name of #include
For example, define the following rules.
As the identifier, only the alphanumeric characters and underscore should be used.
Comments can be written in Japanese. The character code used should be Shift_JIS. 1 byte Kana shall
not be used.
Japanese shall not be used in strings, string constants and file names of #include.
Related rules M4.3.1, M4.3.2, P1.1.1
Compliant example
Rule
specification
Non-compliant example
/* compliant */
char c = '\t';
Preference
guide
Portability
P1.2.2
The language standard defines the following seven nongraphic characters as escape sequences:
\a (alert)
\b (backspace)
\r (carriage return)
\f (form feed)
\t (horizontal tab)
\n (new line)
\v (vertical tab)
Related ruleP1.1.1
131
specifications
of advanced functionalities and implementa
P1.3
1.3
P1.3.1
tion-dependent parts.
Simple char type (that does not specify the signed- Preference
guide
ness) shall be used only for storing character valRule
ues. If a process that depends on signedness (imspecification
plementation-defined) is required, unsigned char or
signed char that specifies its signedness shall be used.
Compliant example
char c = 'a';
/* Used to store characters */
int8_t i8 = -1; /* To use it as 8-bit data,
use a type defined, for
example, with typedef */
Non-compliant example
char c = -1;
if (c > 0) { }
/* Non-compliant: char can be signed or unsigned
depending on the compiler, and this difference
affects the result of the comparison. */
Portability
Unlike other integer types like int , char that does not specify its signedness will be either signed or
unsigned depending on the compiler (int type is the same as signed int type.) Therefore, using char
that depends on the signedness is not portable. This is because char that does not specify its signedness is an independent type provided for storing characters (comprised of three types: char , unsigned
char and signed char ) and the language standard assumes such usage. For using char as a small
integer type, such as, when a process that depends on signedness is required, use either unsigned char
or signed char that specifies its signedness. In this case, it is desirable to use typedef as the type to localize the range of modification during porting.
A problem similar to this rule exists with the returned type of the standard function getc that is int and
must not be received by char . However, this is rather a problem pertaining to function interface (assignment that may cause information loss).
Reference for those seeking further details
Related ruleP2.1.3
132
P1.3.2
Compliant example
Preference
guide
Rule
specification
Non-compliant example
In the C language standard, the members of an enumeration type must have values that can be represented as int type. However, some compilers that support this functionality extendedly may not cause
an error even if the value exceeds the range of int type for the members of an enumeration type.
Reference
C++ allows values in the range of long type for the members of an enumeration type.
Preference
guide
Portability
P1.3.3
Rule
Choose
specification Document
p->bit1 = 1;
Compliant example
Non-compliant example
133
The following behaviors of bit field vary depending on the compiler used:
(1) Whether the bit field of an int type that does not specify its signedness will be handled as signed ;
(2) Assignment order of the bit fields within a unit
(3) Boundary of a bit field in a storage unit
If bit fields are used to access data whose bit positions are meaningful, such as, the IO ports, portability
problem arises due to rules (2) and (3). Therefore, in such cases, do not use bit fields, but instead, use
bitwise operations, such as, & and | .
Related ruleR2.6.1
dependent
P1.4
P1.4.1
Portability
Compliant example
#include <stdio.h>
#include "myheader.h"
#if VERSION == 1
#define INCFILE "vers1.h"
#elif VERSION == 2
#define INCFILE "vers2.h"
#endif
#include INCFILE
Preference
guide
Rule
specification
Non-compliant example
#include stdio.h
/* Neither <> nor is placed */
#include "myheader.h" 1
/* 1 is specified at the end */
In C language standard, the behavior is not defined for cases where the format of the header name does
not match with neither of the two styles (< > or ) after macro-expansion of the #include directive.
Most compilers will output an error if it cannot match the format with neither of the two styles, while
some others may not handle it as an error. Therefore, write the header name format in either of the two
styles to ensure safety.
134
P1.4.2
Compliant example
Preference
guide
Rule
specification
Define
Non-compliant example
#include <stdio.h>
#include "myheader.h"
#include "stdio.h"
#include <myheader.h>
There are two ways of writing #include . To unify the writing style, define rules, for example, that include the following:
Specify the header provided by the compiler by enclosing it with < > ;
Specify the header created in the project by enclosing it with ;
Specify the header provided by the purchased software by enclosing it with .
P1.4.3
Preference
guide
Rule
specification
Portability
Compliant example
#include "inc/my_header.h"
Non-compliant example
/* compliant */
#include "inc\my_header.h"
/* Non-compliant */
The language standard does not define the behavior when the characters mentioned above are used (more
specifically, in the following cases); that is to say, the operation result is not certain when these characters are used in the following cases, which consequently make the code non-portable:.
When characters \ or /* appear in the string enclosed with < > ;
When characters \ or /* appear in the string enclosed with .
Also, the behavior of the character : (colon) differs depending on the compiler, and makes the code
nonportable.
135
P1.5
P1.5.1
Compliant example
#include "h1.h"
Preference
guide
Rule
specification
Non-compliant example
#include "/project1/module1/h1.h"
If an absolute path is written in the code, there will be a need to modify the path when the program is
compiled after changing the directories.
Portability
1
136
Portability
Portability
Portability 2.1
1
2
137
P2.1
2.1
P2.1.1
Preference
guide
When assembly language programs are called
Rule
from C language,how to localize such parts shall
Define
specification
be defined,such as, by expressing them as functions or inline functions of C language that contain only inline assembly language code or describing them using macros.
Compliant example
#define SET_PORT1
void f() {
SET_PORT1;
Non-compliant example
asm("
st.b 1, port1")
void f() {
}
/* asm and other processes are mixed */
In C99, inline-specified functions can be written. Many compilers provide extended support
to asm (string ) format as a method to include the assembly language code. However, there
are some compilers that do not provide such support. Moreover, the same format may lead to
different behavior depending on the compiler used, thus making it non-portable.
Portability
Related rulesM5.1.3P1.1.1P1.1.3E1.1.1
P2.1.2
1
2
Compliant example
138
Preference
guide
Rule
specification
Define
Non-compliant example
/* interrupt is
by a specic
being defined
interrupt void
Some compilers provide extended keywords instead of using the #pragma directive, But the code will
become non-portable when these keywords are used. Therefore, when using them, localize them, such
as, by defining them as macros. For the macro name, use the keyword written in uppercase letters, as
shown above in the compliant example.
Related rule P1.1.1
P2.1.3
Preference
guide
Rule
Choose
specification Document
Non-compliant example
Portability
Compliant example
1
2
The size and internal representation of integer types and floating point types vary depending on the compiler. C99 specifies the following typedefs to be provided as the language standard. Therefore, these
type definitions should be used.
int8_tint16_tint32_tint64_tuint8_tuint16_tuint32_tuint64_t
When using a compiler that supports C90, it is advisable to refer to them as the typedef names for these
basic types.
Related rule P1.3.1
139
Efficiency
Embedded software is characteristic for being embedded
in a product and operating together with hardware to serve
its purposes in the real world. The increasing demand for
further product cost reduction has imposed various restrictions, not only on, such as, MPU or memory, but also on
software.
In addition, requirements, such as, on real-time property
have placed stricter time constraints that need to be met.
Embedded software must therefore be coded with particular
attention on resource efficiency like efficient use of memory
and time efficiency that takes account of time performance.
Efficiency1: Write in a style that takes account of resource and time efficiencies.
Efficiency
Depending on how the source code is written, the object size may increase and the
execution speed may slow down. If there are restrictions on memory size and processing
time, the code must be written thoughtfully with additional considerations given to these
restrictions.
Efficiency 1.1
Efficiency
1
142
E1.1
1.1
E1.1.1
Compliant example
Preference
guide
Rule
specification
Non-compliant example
func1(arg1, arg2);
for (i = 0; i < 10000; i++) {
func2(arg1, arg2); /* Speed performance is
critical for this
process. */
}
func1(arg1, arg2);
for (i = 0; i < 10000; i++) {
func2(arg1, arg2); /* Speed performance is
critical for this
process. */
}
Function is safer than macro function. So, use function as much as possible (see M5.1.3).
However, processing of function calls and returns may slow down the speed performance.
The use of inline function can be one way of preventing the processsing speed from slowing
down. But since inlining is implementation-dependent, inline function may not be expanded
as intended, depending on the complier used. Therefore, if speed performance is an issue that
has to be improved, use macro function instead.
Yet, the frequent use of macro function may increase the object size because the code will be
spread to wherever the macro function is used.
Related ruleM5.1.3
Rule
specification
Non-compliant example
var1 = func();
for (i = 0; (i + var1) < MAX; i++) {
Compliant example
Preference
guide
Operations that remain unchanged shall not be performed within an iterated process.
Efficiency
E1.1.2
143
Repeating the same process that returns the same result is inefficient. Although optimization of the compiler is often reliable for preventing such inefficiency, attention is still necessary in some cases, like in
the non-compliant example shown above, where the compiler used cannot determine the invariance..
E1.1.3
Compliant example
} STAG;
int func (const STAG *p) {
return p->mem1 + p->mem2;
}
Preference
guide
Rule
specification
Non-compliant example
} STAG;
int func (STAG x) {
return x.mem1 + x.mem2;
}
If a structure is passed as a function argument, all the structure data are copied into the area for storing
arguments when the function is called. If the size of the structure is large, it will become the cause of
speed performance degradation.
If a structure passed is read-only, not only pass it as a pointer to the structure, but also qualify it with
const.
E1.1.4
The policy of selecting either switch or if statement shall be determined and defined by taking
readability and efficiency into consideration.
Preference
guide
Rule
specification
Define
switch statements often provide higher readability than if statements. In addition, recent compilers
tend to output optimized code using, such as, table jump or binary search when they process switch
statements. Take these matters into consideration when defining this rule.
Efficiency
1
144
Part
This problem is caused either by putting a statement to branch the program control flow (return,
continue, break, goto statement) into the wrong place, or forgetting to delete unnecessary statements when putting such a branch statement.
146
cnt = 0;
return;
Automatic variables and formal parameters cannot be referenced after the function return. Therefore, if the updated variables are not referenced between the update and the return statement, the
update becomes an unnecessary expression (statement). There is a possibility that some operations
have been missed or unnecessary statements may have been left undeleted due to slippage during
program modification.
return cnt++;
The postfix ++ operation updates the value of the variable after it is referenced, so increments as
shown in the above example are meaningless. If there is a need to return the incremented value to
the caller, the prefix increment must be used.
Overwriting a parameter without referencing its value, as shown in the above example, means that
the value of the argument set by the caller is ignored. This may be a coding error.
147
The program shown in the above example appears to be a correct description at first sight. But in
C language, such description is not interpreted mathematically and is treated as a conditional expression that always becomes true.
if (uc == 256)
switch (uc) {
case 256:
}
if (ui < 0)
The variable is compared with a value beyond the range it can express. uc can only express values
between 0 and 255. ui can never be negative.
The condition shown in the above example compares addresses, and is not a condition for evaluating whether the string abc is equal to the string pointed by str or not.
148
return;
}
In the definition of a function that returns a value, all the return statements must describe the value
to be returned in return expression (as function func1.) In addition, the type of function with one
or more return statements that respectively do not return a value should be void (as function func2.)
In C99, the inconsistency between such type of function and return statement is detected as an error by the compiler.
for (i = 1; i <= N; i++) {/* Accessing outside the array bounds (error) */
var1[i] = i;
}
var1[-1] = 0; /* error */
var1[N] = 0; /* error */
The array index in C language starts with 0 and its maximum value is 1 less than the element
count.
149
tag y;
int *p;
p = func(&y);
*p = 10;
/* Destroying invalid memory area */
*y.mem = 20; /* Destroying invalid memory area */
Areas for automatic variables or parameters are freed to the system when the function ends, and
may be reused for other purposes. If the address of an automatic variable is specified as a function
return value or set in an area that can be referenced by the caller, as shown in the above example,
unexpected faults may occur when the area that has been returned to the system is referenced or updated.
The area for compound literal introduced in C99 is freed and may be reused for other purposes
when the execution proceeds outside the enclosing block of the compound literal.
void f ()
int
150
*p;
p = (int []) {2,
4};
Memories obtained with, such as, malloc function need to be freed to the system by using free
function. The areas that have been freed by free function must not be referenced because they may
be reused by the system.
Depending on the compiler, string literals may be allocated in the const area. Programmers must
therefore be careful not to overwrite string literals.
memcpy(a, b, sizeof(b));
When one array is copied to another, it will corrupt the memory area if the copy is made in the
size of the source that is larger than the size of the destination. The best way to copy from one array
to another is to use arrays of the same size. Or specifying the size of the destination as the copy size
will at least prevent the memory from corrupting.
151
The above example shows a logical product written mistakenly instead of a logical sum. In C language, conditions must be written carefully because they will not be processed as compile error even
if it is not possible to fulfill them.
When a different condition is added as a condition for an iteration statement that sequentially references or updates the array elements to a condition for ensuring that array bounds are not exceeded,
these conditions must be specified with a logical product. The logical sum, as shown in the above
example, may cause the system to access outside the array bounds.
This is an example showing that bitwise AND operator (&) has been written mistakenly instead
of a logical product operator (&&). The bitwise AND operator does not mean that the conditions
are processed to gain a logical product. Make sure that the intention of the program is correctly described.
152
To check whether two values are equal or not, == must be written as the operator instead of =.
Rules to prevent such errors caused by typos include Assignment operators shall not be used in expressions to examine true or false.
There are also reverse cases like a==b; where == operator is written mistakenly instead of = operator. Easy mistake like this must also be carefully avoided.
Example 1: Macro with the same name that has multiple definitions
/* Depending on where AAA is referenced, what is expanded varies */
#define AAA 100
a = AAA;
/* 100 is assigned */
#define AAA 10
b = AAA; /* 10 is assigned */
Macro name defined by #define will not become a compile error in some compilers even when it
is redefined without applying #undef beforehand. Macro name that may be processed differently depending on where it is used should be avoided since it has the risk of impairing the readability of the
program.
153
Some compilers do not cause a compile error even if the const area is rewritten. Programmers
should be careful not to rewrite the const area.
154
Appendices
Appendix A List of practices and rules
Appendix B Rule classification based on C language grammar
Appendix A A
ListList
of practices
and rules
Appendix
of practices
and rules
[Reliability 1] R1 Initialize areas and use them by taking their sizes into consideration.
Practice in detail
R1.1
R1.2
R1.3
Rule
R1.1.1
31
R1.1.2
31
R1.2.1
32
R1.2.2
Initialization of enumeration type (enum type) members shall be by either: not specifying any constants;
specifying all the constants; or specifying only the first
member.
32
R1.3.1
33
R1.3.2
R1.3.3
R1.3.4
156
Appendices
Page
34
34
35
[Reliability 2] R2 Use data by taking their ranges, sizes and internal representations into consideration.
Practice in detail
R2.1
Rule
Page
37
R2.1.2
37
R2.1.3
38
R2.2
R2.2.1
39
R2.3
R2.3.1
Unsigned integer constant expressions shall be described within the range that can be represented with
the result type.
39
R2.3.2
When using conditional operator (?: operator), the logical expression shall be enclosed in parentheses ( ) and
both return values shall be the same type.
39
R2.3.3
40
40
R2.4.2
41
R2.5.1
42
R2.4
R2.5
157
[Reliability 2] R2 Use data by taking their ranges, sizes and internal representations into consideration.
Practice in detail
R2.5
R2.6
R2.7
158
Appendices
Rule
Page
R2.5.2
43
R2.5.3
When ones complement (~) or left shift (<<) is applied to unsigned char or unsigned short type data, an
explicit cast to the type of the operation result shall be
performed.
43
R2.5.4
44
R2.6.1
(1) The types used for bit field shall only be signed int
or unsigned int. If a bit field of 1 bit width is required,
unsigned int type shall be used, and not the unsigned int type.
(2) The types used for bit field shall be signed int,
unsigned int or _Bool. If a bit field of 1 bit width is
required, unsigned int type or _Bool type shall be
used.
(3) The types used for bit field shall be signed int,
unsigned int, _Bool, or those allowed by the compiler that are either enum or the type that specifies
signed or unsigned. If a bit field of 1 bit width is
required, the type that specifies unsigned or _Bool
type shall be used.
44
R2.6.2
46
R2.7.1
47
[Reliability 2] R2 Use data by taking their ranges, sizes and internal representations into consideration.
Practice in detail
R2.7
R2.8
Rule
Page
R2.7.2
50
R2.7.3
50
51
51
52
R2.8.3
Rule
54
R3.1.2
Iteration conditions for a loop to sequentially access array elements shall include the decision to whether the
access is within the range of the array or not.
55
R3.1.3
The size of the array initialized with a designated initializer shall be clearly indicated.
55
R3.1.4
R3.2
Page
R3.2.1
56
57
159
Page
R3.2.2
57
R3.3
R3.3.1
58
R3.3.2
59
R3.4.1
60
R3.4
R3.5
61
R3.5.2
62
R3.6
160
Rule
R3.2
Appendices
R3.5.3
63
R3.6.1
64
R3.6.2
65
R3.6.3
66
Rule
M1.1.2
M1.2
M1.3
M1.4
Page
69
69
M1.2.1
(1) Only one variable shall be declared in one declaration statement (avoid multiple declarations.)
(2) Automatic variables of the same type used for the
similar purposes may be declared in one declaration statement, but variables with initialization and
variables without initialization shall not be mixed.
70
M1.2.2
71
M1.2.3
71
M1.3.1
72
M1.3.2
72
M1.3.3
73
M1.4.1
73
M1.4.2
74
161
M1.6
M1.7
M1.8
162
Appendices
Rule
Page
M1.5.1
74
M1.5.2
75
M1.6.1
75
M1.6.2
76
M1.7.1
77
M1.7.2
78
M1.7.3
79
M1.8.1
80
M1.9
Rule
M1.8.2
Page
80
M1.8.3
81
M1.8.4
81
M1.8.5
82
82
M1.9.2
83
M1.10.1
83
M1.11.1
84
M1.11.2
84
85
86
Rule
Page
M2.1.1
88
M2.1.2
The body of if, else if, else, while, do, for, and switch
statements shall be enclosed into blocks.
88
163
Rule
Page
M2.2.1
89
M2.2.2
90
M2.2.3
90
M2.2.4
91
M3.2
164
Do structured programming.
Appendices
Rule
Page
M3.1.1
93
M3.1.2
94
M3.1.4
95
M3.1.5
96
M3.2.1
96
M3.2.2
Multiple assignments shall not be written in one statement, except when the same value is assigned to
multiple variables.
97
M3.4
Rule
Page
M3.3.1
The three expressions of a for statement shall be concerned only with loop control.MISRA C:2004 13.5
97
M3.3.2
Numeric variables being used within a for loop for iteration counting shall not be modified in the body of the
loop.MISRA C:2004 13.6
98
M3.3.3
98
99
Rule
Page
M4.1
M4.1.1
101
M4.2
M4.2.1
104
M4.3
M4.3.1
106
M4.3.2
106
M4.4
109
M4.4
110
M4.4.3
111
165
Page
111
112
M4.4.6
112
M4.5.1
(1) In a function prototype declaration, all the parameters shall not be named (types only.)
(2) In a function prototype declaration, all the parameters shall be named. In addition, the types of the
parameters, their names and the type of the return
value shall be literally the same as those of the
function definition.
113
M4.5.2
114
M4.5.3
114
M4.6
(1) 0 shall be used for the null pointer. NULL shall not
be used in any case.
(2) NULL shall be used for the null pointer. NULL shall
not be used for anything other than the null pointer.
115
M4.7
M4.7.1
116
M4.7.2
116
M4.5
166
Rule
Appendices
Rule
Page
M4.7.3
117
M4.7.5
117
M4.7.6
118
M4.7.7
119
M5.2
Rule
Page
The rules for writing the code for setting debug options and for recording logs in release modules shall be
defined.
121
M5.1.2
123
M5.1.3
124
M5.2.1
124
Rule
P1.1.2
Page
(1) Functionalities not specified in the language standard shall not be used.
(2) If functionalities not specified in the language standard are used,the functionalities used and their
usage shall be documented.
129
129
167
Page
130
P1.2
P1.2.1
130
P1.2.2
131
P1.3.1
Simple char type (that does not specify the signedness) shall be used only for storing character values.
If a process that depends on signedness (implementation-defined) is required, unsigned char or signed char
that specifies its signedness shall be used.
132
P1.3.2
133
P1.3.3
133
P1.4.1
134
P1.4.2
135
P1.3
P1.4
P1.5
168
Rule
P1.1
Appendices
P1.4.3
135
P1.5.1
136
Rule
Page
138
P2.1.2
138
P2.1.3
(1) The basic types (char, int, long, long long, float, double and long double) shall not be used. Instead, the
types defined by typedef shall be used.The types
defined by typedef that are used in the project shall
be defined.
(2) When using any of the basic types (char, int, long,
long long, float, double and long double) in a form
that is dependent on its size, the type defined by
typedef for each of these basic types shall be used.
The types defined by typedef that are used in the
project shall be defined.
139
[Efficiency1] E1 Write in a style that takes account of resource and time efficiencies.
Practice in detail
E1.1
E1.1
Rule
Page
143
E1.1.2
Operations that remain unchanged shall not be performed within an iterated process.
143
E1.1.3
144
144
169
No.
Rule
1. Style
1.1
Syntax style
M4.1.1
Conventions regarding the style of using, such as, the braces{ }, indentation
and space shall be defined.
1.2
Comments
M4.2.1
1.3
Naming
M1.7.1
M1.7.2
Names for functions, variables and macros in the standard library shall not be
redefined or reused. In addition, those macro names shall not be undefined.
M1.7.3
1.4
170
M4.3.1
M4.3.2
The descriptive contents of header files (declarations, definitions, etc) and the
order they are described in shall be defined.
M4.4.2
The descriptive contents of source files (declarations, definitions, etc) and the
order they are described in shall be defined.
M4.4.3
M4.4.5
Appendices
Classification based
on the grammar
No.
Rule
1. Style
1.4
1.5
Constants
1.6
Other (Style)
M1.2.3
When expressing a long string literal, successive string literals shall be concatenated without using newlines within the string literal.
M1.2.2
Suffixes shall be added to constant descriptions that can use them to indicate
appropriate types. Only an uppercase letter L shall be used for a suffix indicating a long type integer constant.
M1.8.5
A sequence starting with zero (0) that is two or more digits long shall not be
used as a constant.
M1.10.1
M1.1.2
M1.8.4
M1.9.1
M5.1.3
P1.3.1
Simple char type (that does not specify the signedness) shall be used only
for storing character values. If a process that depends on signedness (implementation-defined) is required, unsigned char or signed char that specifi es its
signedness shall be used.
P2.1.3
(1) The basic types (char, int, long, long long, float, double and long double)
shall not be used. Instead, the types defined by typedef shall be used.The
types defined by typedef that are used in the project shall be defined.
(2) When using any of the basic types (char, int, long, long long, fl oat, double
and long double) in a form that is dependent on its size, the type defined
by typedef for each of these basic types shall be used.The types defined
by typedef that are used in the project shall be defined
R2.6.2
Data used as bit sequences shall be defined with unsigned type, and not with
the signed type
2. Type
2.1
Basic types
171
Classification based
on the grammar
No.
Rule
2. Type
2.2
2.3
2.4
Structures/Unions
Bit fields
Enumerated type
R2.1.3
M1.6.2
M1.7.2
Names for functions, variables and macros in the standard library shall not be
redefined or reused. Inaddition, those macro names shall not be undefined.
M4.5.2
R2.6.1
(1) The types used for bit field shall only be signed int or unsigned int. If a bit
field of 1 bit width is required, unsigned int type shall be used, and not the
unsigned int type
(2) The types used for bit field shall be signed int, unsigned int or _Bool. If a
bit field of 1 bit width is required, unsigned int type or _Bool type shall be
used.
(3) The types used for bit field shall be signed int, unsigned int, _Bool, or
those allowed by the compiler that are either enum or the type that specifi
es signed or unsigned. If a bit field of 1 bit width is required, the type that
specifi es unsigned or _Bool type shall be used.
P1.3.3
R1.2.2
M2.2.4
enum shall be used rather than #define when defi ning related constants.
P1.3.2
The members of an enumeration type (enum) shall be defined with values that
can be represented as int type.
R1.1.1
R1.1.2
R1.2.1
Arrays with specifi ed number of elements shall beinitialized with values that
match the number of the elements.
3. Declaration/Definition
3.1
172
Initialization
Appendices
Classification based
on the grammar
No.
Rule
3. Declaration/Definition
3.1
3.2
Initialization
M2.1.1
If arrays and structures are initialized with values other than 0, their structural
form shall be indicated by using braces { }. Data shall be described without
any omission, except when all values are 0.
M4.5.3
(1) , shall not be placed before the last } in the list of initial value expressions for structures, unions and arrays, nor in the list of enumerators
(2) , shall not be placed before the last } in the list of initial value expressions for structures, unions and arrays, nor in the list of enumerators.
However, placing , before the last } in the list of initial values for array
initialization is allowed.
M1.6.1
M1.11.1
M1.11.2
Areas that may be updated by other execution units shall be declared as volatile.
M1.11.3 Rules for variable declaration and definition for ROM ization shall be defined
3.3
M2.2.1
Variables used only in one function shall be declared within the function.
M2.2.2
Variables accessed by several functions defined in the same file shall be declared with static in the file scope.
M4.4.4
(2) When using functions with a variable number of arguments, they shall be
used after documenting the intended behaviors based on the compiler used.
R2.8.3
One prototype declaration shall be made at one place from where it can be
referenced by both the function calls and function defi nition.
173
Classification based
on the grammar
No.
Rule
3. Declaration/Definition
3.3
3.4
R3.1.4
3.5
Functions that are called only by functions defined in the same file shall be
static.
(1) In a function prototype declaration, all the parameters shall not be named
(types only.)
(2) In a function prototype declaration, all the parameters shall be named.
In addition, the types of the parameters, their names and the type of the
return value shall be literally the same as those of the function defi nition.
(1) In an extern declaration of an array, the number of elements shall always be
specified.
(2) In an extern declaration of an array, the number of elements shall always
be specified, except for extern declarations of arrays that correspond to the
array defi nition that includes initialization and has omitted the number of elements.
Variable length array type shall not be used.MISRA C:2012 R18.8
M1.3.3
The types shall be explicitly described for defi nitions and declarations of functions and variables.
R3.3.1
R3.3.2
The function shall check if there are constraints on parameters before starting
to process
4. Expression
4.1
Function call
R3.4.1
4.2
174
Pointer
Appendices
R2.7.1
Classification based
on the grammar
No.
Rule
4. Expression
4.2
4.3
4.4
Pointer
Cast
Unary operation
R1.3.1
(1) Integer addition to or subtraction from (including ++ and --) pointers shall not
be made; Array format with [ ] shall be used for references and assignments
to the allocated area.
(2)Integer addition to or subtraction from (including ++ and --) pointers shall be
made only when the pointer points to the array and the result must be pointing within the range of the array.
R1.3.2
R1.3.3
Comparison between pointers shall be used only when the two pointers are
both pointing at either the elements in the same array or the members of the
same structure.
R2.7.3
R3.2.2
M3.4.1
M4.6.1
(1) 0 shall be used for the null pointer. NULL shall not be used in any case.
(2) NULL shall be used for the null pointer. NULL shall not be used for anything
other than the null pointer.
R2.4.2
R2.7.2
A cast shall not be performed that removes any const or volatile qualification
from the type addressed by a pointer.MISRA C:2012 R11.8
R2.5.2
R3.6.3
sizeof operator shall not be used in expressions that have side effect.
M1.5.1
A function identifier (function name) shall only be used with either a preceding
&, or with a parenthesized parameter list, which may be empty.
MISRA C:2004 16.9
175
Classification based
on the grammar
No.
Rule
4. Expression
176
4.5
R3.2.1
Operations shall be performed after confi rming that the right-hand side expression of division or remainder operation is not 0.
4.6
Shift
R2.5.4
The right-hand side of a shift operator shall be zero or more, and less than the
bit width of the left-hand side.
4.7
Comparison
R2.1.1
R2.2.1
Comparison with a value defined as true shall not be made in expressions that
examine true or false.
M1.5.2
4.8
Bit operation
R2.5.3
When ones complement (~) or left shift (<<) is applied to unsigned char or
unsigned short type data, an explicit cast to the type of the operation result
shall be performed.
4.9
Logical operation
M1.4.1
Expressions described at the right hand and left hand of && and || operations
shall be either simple variables or expressions enclosed with ( ). However, if
only && operations or only || operations are successively combined, it is not
necessary to enclose each && and || expression with ( ).
M1.8.1
The right-hand operand of a logical && or || operator shall not contain side effects. MISRA C:2004 12.4
R2.3.2
When using conditional operator (?: operator), the logical expression shall be
enclosed in parentheses ( ) and both return values shall be the same type.
4.11 Assignment
R2.4.1
When the type of an operation and the type of the destination to which the
operation result is assigned (assignment destination) are different, the operation shall be performed after casting them to the type of expected operation
precision.
R2.5.1
When performing assignments (=operation, actual arguments passing of function calls, function return) or operations to data types that may cause information loss, they shall be first confirmed that there are no problems, and a cast
shall be described to explicitly state that they are problem-free.
Appendices
Classification based
on the grammar
No.
Rule
4. Expression
4.11 Assignment
M3.3.3
4.12 Comma
M3.2.1
R3.6.1
R3.6.2
Function calls with side effects and volatile variables shall not be described
more than once in a sequence of actual arguments or binary operation expressions.
M1.4.2
R2.3.1
5. Statement
5.1
if statement
R3.5.1
5.2
switch statement
M3.1.4
(1) Each case clause and default clause in a switch statement shall always
end with a break statement.
(2) If the case clause or default clause in a switch statement is not going to
be ended with a break statement, a project-specifi c comment shall be
definedand that comment shall instead be inserted
R3.5.2
177
Classification based
on the grammar
No.
Rule
5. Statement
5.2
5.3
switch statement
for/while statement
M1.3.1
M1.3.2
The case labels and default label in a switch statement shall be described only
in the compound statement (excluding nested compound statements) within
the body of the switch statement.
R2.1.2
R2.3.3
Loop counters and variables used for comparison of loop iteration conditions
shall be the same type.
R3.1.2
R3.5.3
Equality operators (==) or inequality operators (!=) shall not be used for comparisons of loop counters. (<=, >=, <, or > shall be used.)
M1.9.2
5.4
178
Other (statement)
Appendices
M3.1.1
For any iteration statement, there shall be at most one break statement used
for loop termination.MISRA C:2012 R15.4
M3.3.1
The three expressions of a for statement shall be concerned only with loop
control. MISRA C:2004 13.5
M3.3.2
Numeric variables being used within a for loop for iteration counting shall not
be modifi ed in the body of the loop.MISRA C:2004 13.6.
M2.1.2
The body of if, else if, else, while, do, for, and switch statements shall be enclosed into blocks.
M3.1.2
M3.1.5
Classification based
on the grammar
No.
Rule
5. Statement
5.4
Other (statement)
M3.2.2
Multiple assignments shall not be written in one statement, except when the
same value is assigned to multiple variables.
M4.7.2
#else, #elif or #endif that correspond to #ifdef, #ifndef or #if shall be described
in the same file, and their correspondence relationship shall be clearly stated
with a comment defined in the project .
M4.7.3
M4.7.7
P1.4.1
6. Macro/preprocessor
6.1
6.2
#if related
#include
P1.4.2
6.3
6.4
Macro
The usage of <> format and format for #include file specifi cation shall be
defined.
P1.4.3
Characters , \, , /*, // and : shall not be used for file specifi cation in #include.
P1.5.1
The absolute path shall not be written for #include file specification.
M1.8.2
M4.7.1
The body and parameters of a macro that includes operators shall be enclosed with parentheses ( ).
M4.7.5
M4.7.6
179
Classification based
on the grammar
No.
Rule
6. Macro/preprocessor
6.4
R20.10
(2) A macro parameter immediately following a # operator shall not immediately be followed by a ## operator.MISRA C:2012 R20.11
7. Environment/Other
7.1
Portability
P1.1.1
P1.1.2
7.2
180
Performance
Appendices
(1) Functionalities not specifi ed in the language standard shall not be used.
(2) If functionalities not specifi ed in the language standard are used,the
functionalities used and their usage shall be documented.
All usage of implementation-defined behavior shall be documented.
MISRA C:2004 3.1
P1.2.1
To use characters other than those defined in the language standard for
writing a program, the compiler specifi cations shall be confirmed, andtheir
usage shall be defined.
P1.2.2
P1.1.3
To use a program written in another language,its interface shall be documented and its usage shall be defined.
P2.1.1
When assembly language programs are called from C language,how to localize such parts shall be defined,such as, by expressing them as functions
or inline functions of C language that contain only inline assembly language
code or describing them using macros.
P2.1.2
E1.1.1
R1.3.4
E1.1.2
E1.1.3
E1.1.4
Classification based
on the grammar
No.
Rule
7. Environment/Other
7.3
M5.1.1
The rules for writing the code for setting debug options and for recording logs
in release modules shall be defined.
7.4
Other
M5.2.1
181
Ci t a t i o n s a n d Re f e r e n c e s
[1] ISO/IEC 25010:2011, Systems and software enginieering -- Systems and software Quality Requirements and
Evaluation (SQuaRE) -- System and software quality models.
[2] ISO/IEC 9899:1990, Programming languages C, ISO/IEC 9899:1990/Cor 1:1994, ISO/IEC 9899:1990/Cor 2:1996,
ISO/IEC 9899:1990/Amd 1:1995, C Integrity
[3] ISO/IEC 9899:1999, Programming languages C, ISO/IEC 9899/Cor1:2001
[4] ISO/IEC 14882:2003, Programming languages C++
[5] MISRA Guidelines for the Use of the C Language in Vehicle Based Software, The Motor Industry Software
Reliability Association, ISBN 0-9524156-9-0, Apr. 1998, www.misra-c.com
[6] MISRA-C:2004 Guidelines for the Use of the C Language in Critical Systems, The Motor Industry Software
Reliability Association, ISBN 0-9524156-2-3, Oct. 2004, www.misra.org.uk
[7] MISRA C:2012 Guidelines for the Use of the C Language in Critical Systems,March. 2013, ISBN 978-1-90640010-1, www.misra.org.uk
[8] Indian Hill Style and Coding Standards, ftp://ftp.cs.utoronto.ca/doc/programming/ihstyle.ps
[9] comp.lang.c Frequently Asked Questions, http://www.eskimo.com/~scs/C-faq/top.html
[10] GNU coding standards, Free Software Foundation, http://www.gnu.org/prep/standards/
[11] The C Programming Language, Second Edition, Brian W. Kernighan and Dennis M. Ritchie, ISBN 0-13-1103628, Prentice Hall PTR, Mar. 1988
[12] Writing Solid Code: Microsoft's Techniques for Developing Bug-Free C Programs, Steve Maguire, ISBN
1-55615-551-4, Microsoft Press, May. 1993
[13] The Practice of Programming, Brian W. Kernighan and Rob Pike, ISBN 0-201-61586-X, Addison-Wesley
Professional, Feb. 1999
[14] Linux kernel coding style, http://www.kernel.org/doc/Documentation/CodingStyle
[15] C Style: Standards and Guidelines: Defining Programming Standards for Professional C Programmers, David
Straker, ISBN 0-1311-6898-3, Prentice Hall, Jan. 1992
[16] C Programming FAQs:Frequently Asked Questions, Addison-Wesley Professional, Nov. 1995. ISBN
9780201845198, Steve Summit
[17] C STYLE GUIDE (SOFTWARE ENGINEERING LABORATORY SERIES SEL-94-003), NASA, Aug. 1994,
http://sel.gsfc. nasa.gov/website/documents/online-doc/94-003.pdf
[18] The CERT C Secure Coding Standard, Robert C. Seacord, ISBN 978-0321563217, Addison-Wesley Professional,
Oct. 2008
182
References
IPA/SEC
IPA/SEC
Mitsubishi Space Software Co., Ltd.
Matsushita Electric Industrial Co., Ltd.
TOYO Corporation
GAIA System Solutions Inc.
TOSHIBA CORPORATION
IPA/SEC
NEC Corporation
IPA/SEC
OGIS-RI Co., Ltd.
IPA/SEC
Ricoh Company, Ltd.
eSOL Co., Ltd.
Fujitsu Limited
Matsushita Electric Industrial Co., Ltd.
TOYO Corporation
Fujitsu Limited
IPA/SEC
NEC Corporation
Hitachi, Ltd.
eSOL Co., Ltd.
Nagoya University
IPA/SEC
(Organizational affiliations are as of the publication of Japanese edition.)
IPA/SEC
Shimizu International
IPA/SEC
IPA/SEC
183
ESCR
Revised edition
Embedded System development Coding Reference guide [C language edition]
Ver.2.0
July 24, 2014
Written and edited by Software Reliability Enhancement Center,
Technology Headquarters,Information-technology Promotion Agency, Japan
http://www.ipa.go.jp/english/sec/
Copyright 2014, IPA/SEC