Embedded C Coding Standard
Embedded C Coding Standard
Revised Edition
i
This document is the English edition of ESCR (Embedded System development Coding
Reference) [C language edition] Version 3.0 published by IPA/SEC* in Japan. It is the revised
English edition of ESCR [C language edition] Version 2.0 made available in July 2014 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.
March 2018
Software Reliability Enhancement Center, Technology Headquarters,
Information-technology Promotion Agency, Japan
C opyrigh t © 20 1 8 , I P A / S E C
P erm ission to copy an d distrib ute th is docum en t is h ereb y gran ted prov ided th at th is n otice is retain ed on all copies, th at
copies are n ot altered, an d th at I P A / S E C is credited wh en th e m aterial is used to f orm oth er copyrigh t policies.
* S of tware R eliab ility E n h an cem en t C en ter, T ech n ology Headquarters, I n f orm ation - tech n ology P rom otion A gen cy, J apan
ii
P reface
O n p ublication of E SCR [ C lang uag e edition] V er. 3 . 0
This document is the English edition of ESCR (Embedded System development Coding Reference) [C
language edition] Version 3.0, with the aim to improve the quality of the source code written in C language
by collecting the important points to be noted as a part of the know-how for coding and organizing them as
practices and rules.
ESCR was first released in June 2006. Exactly a year later (in June 2007), Version 1.1 was released with
minor changes to reflect the feedback from various users and reviewers who pointed out some areas that
lacked in accuracy or clarity. Then in March 2014, Version 2.0 was released mainly to comply with C99, the
most widely used C language standard at the time, as well as to align with the extensively revised version of
MISRA C (MISRA C:2012) issued in March 2013.
ESCR Version 3.0 is the immediate successor of Version 2.0. Along with supplementary explanatory texts,
additional compliant and non-compliant coding examples, and warnings specifically focused on reminding
the coders about the growing importance of taking security into consideration more carefully when they
write the code, Version 3.0 contains new rules and descriptions that mainly consist of the following:
・R ules on C E R T C C odin g S tan dard th at h av e b een dev eloped b y th e S of tware E n gin eerin g I n stitute in
C arn egie M ellon U n iv ersity ( C M U / S E I )
・R ules proposed b y I P A I T S ecurity C en ter as im portan t poin ts to k eep in m in d to elim in ate v uln erab ilities
durin g dev elopm en t
Furthermore, the rules and descriptions revised in ESCR C++ Version 2.0 (the latest ESCR edition for
C++ language) that also apply to C language have been updated in this document.
To maintain the continuity from the previous release, ESCR Version 3.0 follows the same 3-part structure
as Version 2.0, including the same numbering system applied to practices and rules carried over from the
previous version.
The primary purpose of this document remains consistent from the initial release in 2006. It is intended
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. In addition to that, Version 3.0 has introduced a set of new rules and descriptions
that mainly address the growing need for more security-conscious implementation in embedded products
and solutions that could effectively help eliminate vulnerabilities in software at the coding level for safer
deployment and adoption of IoT that is becoming increasingly widespread.
We sincerely hope that the effective use of ESCR Version 3.0 will lead to the improvement of embedded
software productivity and contribute to the attainment of high-quality software development.
Spring of 2018
Yukihiro Mihara, Keisuke Toyama
Software Reliability Enhancement Center, Technology Headquarters
Information-technology Promotion Agency, Japan
Fusako Mitsuhashi
Coding Practice Guide Revision Working Group
Preface iii
Table of Contents
Part
1 How to Read the Coding Practices Guide 1
1 O ve rvi ew. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1 W h at are C odin g P ractices? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3 How to U se th is G uide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 8
3.1 S cen arios f or U sin g th is G uide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 8
Part
2 Coding Practices for Embedded Software: Practices Chart 23
How to R ead th e P ractices C h art .............................................................. 24
T erm in ology U sed in th e P ractices C h art ................................................... 28
C odin g P ractices f or E m b edded S of tware .................................................. 29
● R eliab ility .................................................................................................................. 3 1
● E f f icien cy ................................................................................................................ 1 4 7
iv T ab le of C on ten ts
Part
3 Typical Coding Errors in Embedded Software 1 5 1
T ypical C odin g E rrors in E m b edded S of tware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 5 2
1 M ean in gless exp ression s an d statem en ts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 5 2
Appendices 1 6 1
A ppen dix A L ist of practices an d rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 6 2
A ppen dix B R ule classif ication b ased on C lan guage gram m ar . . . . . . . . . . . . . . . . . . . 1 7 6
A ppen dix C R egardin g th e im plem en tation - def in ed b eh avi ors . . . . . . . . . . . . . . . . . . . . . 1 8 9
T ab le of C on ten ts v
Part 1
How to Read the
Coding Practices Guide
1 O v erv iew
1 .1 W hat are Coding Practices?
1 .2 Purpose and Position of Coding Practices and the Target U sers
1 .3 Characteristics of the Coding Practices
1 .4 N otes on U sing this Guide
1.1 W
1.1 hat
W h aare
t aCoding
r e c o d iPractices?
n g p r a c t i c e s?
Creating source code (code implementation) is an inevitable task for developing embedded soft-
ware. 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 uality of programs written in
C thus tends to reflect uite clearly the difference in coding skill level between seasoned and less-
ex perienced 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 organization-
wide or group-wide.
1 ) T h e n ecessity of rules is n ot un derstood. T h e appropriate m eth ods to deal with rule v iolation s are
also n ot widely sh ared.
2) T h ere are too m an y rules to learn . Y et, th e ex istin g rules are n ot com pr eh en siv e en ough to cov er
th e en tire scope of codin g.
3 ) S in ce h igh ly reliab le tools th at can th orough ly an d accurately ch eck wh eth er th e written code is
com plyin g with th e relev an t rules or n ot are un av ailab le, th e en gin eers h av e to rev iew th e code
m an ually th rough v isual ch eck , wh ich is a h eav y b urden f or th em .
D ue to such circumstances, there are, in fact, some coding conventions established at the organi-
ation or department level that have lost their significance and are no longer strictly observed.
N evertheless, organizations that have coding conventions, no matter what kind of format they
1 ●O ve rvi ew 3
Target U sers
This guide has been written on the assumption that it will be read by the following types of users
B enefits Gained
The benefits that the users can expect to gain directly from using this guide are as mentioned
above. oreover, 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.
1.3 Characteristics
1.3 Ch a r a c t e r i s tof
i cthe
s o Coding
f t h e C Practices
o d i n g Pr a c t i c e
1 ●O ve rvi ew 5
1.4 N
1.4 otes onon
N otes U sing
usingthis
thisGuide
guide
- L ib rary f un ction s
- M etrics ( n um b ers of lin es in f un ction s/ com plex ity of f un ction s, etc. )
Although Errors in writing possibly classified as coding errors have been excluded from the ref-
erence rules, some frequently observed coding errors collected while preparing this guide are ex em-
plified in art 3 Typical Coding Errors in Embedded Software. This section ( art 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 pro ect teams that find it meaningful to establish rules to pre-
vent coding errors from being caused by such common pitfalls in programming.
C9 0
This is the C language standard defined in IS IEC 1 0 rogramming anguage C . It is
often called C 0, where 0 stands for the year IS IEC 1 0 was published. The C language
standard has been revised and is now C , making C 0 an older version.
C11
This is the most recent C language standard defined in IS IEC 2011 rogramming an-
guage C and thereby is the current C language standard. Since IS IEC 2011 was published
in 2011, it is often called “ C11” .
C+ +
This is the C language standard defined in IS IEC 1 2 2003 rogramming language C .
M I SRA C
It refers collectively to the coding guidelines for C language defined by The otor Industry Soft-
ware Reliability Association ( ISRA) in , which include ISRA C 1 , ISRA C 200 and
MISRA C:2012.
M I SRA C:19 9 8
The convention in Citations and References .
M I SRA C:20 0 4
The convention in Citations and References 6 . This is the revised version of ISRA C 1 .
M I SRA C:20 12
The convention in Citations and References 7 . This is the revised version of ISRA C 200 .
For the names of variables and functions used in code ex amples, this guide uses notations that are
as simple as possible to prevent the users from becoming confused or misunderstanding the rules un-
necessarily.
1 ●O ve rvi ew 7
U sing static code analysis tools
The method of using static code analysis tools designed to detect bugs through the static analysis
of the source code is not included in the scope of this guide. ut this is an effective means to ensure
that coding rules are fully met while coding, and is therefore highly recommended as a reliable tool
to prevent coding errors. In ISRA C and CERT C, which are both referenced in this guide, there
are descriptions indicating the rules where the static code analysis tools can report the violations.
A compiler can be considered as the simplest form of static code analysis tool available. Many
compilers can detect problems in the source code if the warning levels are appropriately set. y uti-
lizing the warnings generated from the compiler, the programmers can often eliminate problems in
the source code at an early stage.
This document (Ver. 3.0) has been updated from the previous version (Ver. 2.0) primarily by add-
ing rules on secure coding. Along with supplementary ex planatory tex ts, additional compliant and
non-compliant coding examples, and warnings specifically focused on reminding the programmers
about the growing importance of taking security into consideration more carefully when they write
the code, Version 3.0 contains new rules and descriptions that mainly address the growing need for
more security-conscious implementation in embedded products and solutions that could effectively
help eliminate vulnerabilities in software at the coding level. Furthermore, the revisions made in
ESCR C Version 2.0 (the latest ESCR edition for C language) that are common to both C and
C are also updated in this document. There are also descriptions that deal with the same matters
ex plained in Ver. 2.0 but have been rewritten in this document with more clarity or in a way that
would be easier to understand.
The rules carried over from Ver. 2.0 without any changes in the description are numbered the
same in this document so that the ESCR users who are already familiar with the structure of the pre-
vious version can find this updated version easy to use.
The practices and rules that have been newly added to this document are R3.1. , R3.11, R3.11.1,
R3.11.2 and P1.5 .2.
2.1 Q
2.1 uality Characteristics
Q uality Characteristics
or many, speaking of software uality would remind them of bugs. owever, in the field of
software engineering, the uality 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
2 010 2011 1 .
IS IEC 2 010 2011 defines the uality of software product by breaking it down into eight char-
acteristics ( uality characteristics) reliability , maintainability , portability , efficiency , secu-
rity” , “ functionality” , “ usability” and “ compatibility”
Among them, “ functionality” , “ usability” and “ compatibility” are considered to be the three qual-
ity characteristics that should be addressed at an early stage, preferably before moving on to the
design phases in the upstream process. Whereas, “ reliability” , “ maintainability” , “ portability” , and
efficiency are considered to be the uality characteristics that have close relevance with the devel-
opment of high-quality source code and should therefore be ex amined in depth during the coding
phase. Security , which has been defined as the uality subcharacteristic of functionality in the
previous standard, IS IEC 126-1, is considered basically as a uality characteristic that is relevant
in the design phase, but coding such as for avoiding stack overflow can also affect security. or more
information on coding practices related to security, please refer to the outline of the column below
and CERT C Coding Standard 1 .
ased on the above broad categori ation, this guide has adopted the latter four uality charac-
teristics - “ reliability” , “ maintainability” , “ portability” , and “ efficiency” - as the main focus, and
gathered the coding practices that are primarily concerned with any of these four. Table 1 shows the
relationship between the uality characteristics defined in IS IEC 2 010 and the code uality
proposed in this guide, along with the “ quality subcharacteristics” .
It is important not to mis udge whether the data is under your control or not. The cookies of a da-
tabase ( ) or website that can be manipulated by other systems as well or data that has once being
placed outside your control may be overlooked by misunderstanding it to be still under your control.
ness and efficiency is composed of discrete components such that a which the
with which a prod- change to one component has minimal impact on components
uct or system can other components are composed
be modified by the such that a
intended maintainers change to one
component of
the code has
minimal im-
pact on other
components.
Performance relative Time ehav- D egree to which the response and process- Efficiency
Performance Efficiency
to the amount of iour ing times and throughput rates of a product or with regard
resources used under system, when performing its functions, meet to processing
stated conditions requirements time
product or system data are accessible only to those authorized to tainty that data
protects information have access are accessible
and data so that persons only to those
authorized to
or other products or
have access
systems have the
degree of data access
Integrity D egree to which a system, product or component D egree of
appropriate to their
prevents unauthori ed access to, or modification prevention of
types and levels of
of, computer programs or data unauthorized
authorization access to, or
modification
of, computer
programs or
data
Rules
O v erall Structure
In this guide, the basic matters to be followed when creating source code are organized as “ prac-
tices . or 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, accord-
ing to their association to any of the four uality characteristics described earlier in 2.1. The follow-
ing section defines what practice and rule actually mean in this guide (see also igure 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.
Language dependent
Rules:
The body of if, else if, else, Variables used only in one
Reference while, do, for, and switch function shall be declared within
information of statements shall be enclosed into the function.
blocks.
specific coding
rules that take
language Functions that are called only by
dependency into ・
・・ functions defined in the same file ・
・・
shall be static.
consideration.
U sage Scenarios
This guide intends to support the creation of coding conventions, and assumes that it will be used
in the following three scenarios:
Serv ing as a L earning M aterial for Programmers’ Training and Self- Study
There are many books published on C language. nlike those existing ones, this guide focuses on
implementation quality, and provides an organized set of information on how to create source code
that can maintain and improve its quality. In this sense, this guide can also be an ex cellent material
for the users to learn about source code quality from a more practical point of view.
W hen 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
Proj ects creating a new coding convention of their own are recommended to follow the procedure
described below, step by step:
After following these steps in order, add any other rules as needed.
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 ractices Chart in art 2, based on the cre-
ation policy decided in Step-1. If the proj ect decides on the policy that prioritizes on portability, for
ex ample, efforts should be made to include many rules that address the portability issues in its cod-
ing 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 indi-
cated with , which would result in a set of widely applied rules.
1 ) R ules th at can b e used as a part of th e codin g con v en tion with out m ak in g an y ch an ges ( I n th e
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 pro ect. In doing so, the supplementary explanation provided to each prac-
tice described in this guide should serve as a useful reference on rule definition.
- D escrib e wh at prob lem s m ay occur b y writin g code th at is com plian t with th e rule;
- Hav e ex perts rev iew th e prob lem s an d possib le solution s;
- R ecord th e rev iew result.
e sure not to allow exceptions too easily. The substance of the rule will be lost when there
are too many ex ceptions.
The following is an example of the procedure for allowing exceptions.
[ Ex ample procedure]
( 1 ) P repare a f orm describ in g th e reason f or th e ex ception .
( T h is f orm sh ould, f or ex am ple, con tain th e f ollowin g item s. ) - R ule n um b er;
f orm .
3.3 Enhancing
3.3 E n h a n c iEx
n gisting
ex i s tCoding
i n g c oConv
d i n g entions
c o nv e n t i o n s
For proj ects where coding conventions already ex ist, this guide can be a useful reference to re-
view and enhance the contents of their coding conventions.
This guide is a good learning material for programmers who have studied C language but are still
not used to or have little ex perience in practical coding.
Target U sers
● Efficiency
H owtotRead
How o Rethe
a dPractices
t h e PrChart
a c t i c e s Ch a r t
O rganiz ational Structure of the Practices
Coding practices shown in art 2 are classified according to four software uality characteristics
(reliability, maintainability, portability, efficiency).
Practices in O utline
ractices closely related to each characteristic are largely divided into practices in outline .
or example, the practices closely related to maintainability are largely divided into five practices
in outline from aintainability 1 eep in mind that others will read the program to
aintainability rite in a style that makes testing easy .
Practices in D etail
Each practice in outline is broken down into more specific subsets called practices in detail . or
example, the practice in outline aintainability 3 rite programs simply has four practices in
detail, which are
⑤ Preference guide
Reliability Reliability
I nitializ e areasI nitializande use
areas them
and byuse them by U se areasR afterU initializ
se areas ingafter
them.initializ ing them.
1 1
ReliabilityReliability
ReliabilityReliability
R 1 .1 1 .1
ReliabilityReliability
ReliabilityReliability
Reliability
tak Reliability
ing their siztak es
inginto
their
consideration.
siz es into consideration.
I nitializ e areasI nitializ
ande use
areas and by
them use them by R1.1.1 U se
R1.1.1
areasR after U initializ
se areas ingafter
them. initializ ing them.
1 1
R 1 .1 Automatic 1 v . ariables
1 Automatic
shall be initializ
v ariables
ed atshall
the be
time P ref eren
initializ edceat the● time P ref eren ce
●
guide guide
tak ing their siz tak es
inginto
their siz es into consideration.
consideration. of declaration, or theofinitial declaration,
v alues shall or thebeinitial
assigned
v alues shall R ule
be assigned R ule
j ust before using them. j ust before using them.
Various variables are Various
used in programs
variables are
written
usedininCprograms
language.written
Without in considering
C language.the Without considering the R1.1.1 R1.1.1
Automatic v ariablesAutomatic v ariables
shall be initializ ed atshall
the betime initializ edceat the● time
P ref eren
guide
P ref eren ce
guide
●
1
1
areas to be reserved inareas
the computer
to be reserved
and ensuring
in the computer
that theseand
areas
ensuring
are already
that these
initialized
areas are
by already initialized by
⑥ ule specification
of declaration, or theofinitial declaration,
v alues shallor thebeinitial
assignedv alues shall be assigned
R ule R ule
the time these variablesthe aretime
used,
these
unexvariables
pected malfunctions
are used, unexmaypected
occur.
malfunctions may occur. Compliant ex j ust beforeCompliant
ample using them. j ust before using
ex ample them.ex ample
N on- compliant N on- compliant ex ample
Various variables are Various variables are
used in programs usedininCprograms
written language.written
Without in considering
C language.the Without considering the void func() { void func() {
Moreover, the pointersMoreover,
in C language
the pointers
need to inbeCused
language
carefully
needbytobeing
be used
conscious
carefully
of by
thebeing conscious of the void func() { void func() {
1
1
1
1
intthe var1; int var1;
areas to be reserved inareas to be reserved
the computer in the computer
and ensuring that theseand ensuring
areas that these
are already areas are
initialized by already initialized by int var1 = 0; // Initializeint at var1
the time
= 0; //
of Initialize at time of
areas they point to. Sinceareasthethey
misuse
pointofto.pointers
Since the
may misuse
causeofserious
pointers
problems
may cause
to the
serious
entireproblems to the entire // declaration // declaration var1++; var1++;
the time these variablesthe aretime these
used, unexvariables are used, unexmay
pected malfunctions pected malfunctions may occur.
occur. Compliant Compliant
int i; ex at
int i; ex ample// Do not initialize ample
the N on-… compliant
// Do not initialize ex ample
at the N on-… compliant ex ample
system, particular cautionsystem,
is necessary
particular
when
caution
usingis them.
necessary when using them. // time of declaration }
// time of declaration
void func() {
}
void func() {
Moreover, the pointersMoreover, the pointers
in C language need to inbeCused
language needbytobeing
carefully be used carefully
conscious of by
thebeing conscious of the void func() {
...
void func() {
...
“ Reliability 1” consists“ of
Reliability
the following
1” consists
three practices.
of the following three practices. int var1 = 0; // Initializeint
var1++;
at var1
var1++;
= 0; //
the time of Initialize atintthe var1;
time of int var1;
areas they point to. Sinceareasthethey pointofto.pointers
misuse Since the
may misuse
causeofserious
pointers may cause
problems serious
to the entireproblems to the entire // declaration
// Assign the initial value // just
Assign
before
// declaration var1++;
the initial value just
… before
var1++;
…
int i; int i;
// Do not initialize at the// Do not initialize at the
system, particular cautionsystem, particular
is necessary caution
when usingis them.
necessary when using them. // using it // using it
// time of declaration
for (i = 0; i < 10; i++) {for (i = 0; i < 10; i++) {
}
// time of declaration }
⑦ Compliant ex ample
... ...
“ Reliability 1” consists“ of
Reliability 1” consists
the following of the following three practices.
three practices. …
var1++;
…
var1++;
} }
Reliability 1.1 U se areas after
Reliability 1.1 initializ
U se ingareasthem.
after initializ ing them. }
// Assign the initial value
// using it
}
// just
Assign
// using it
the initial value just before
before
⑨ Remark s
Pay attention to thePay attention
range of the to thepointed
area range of
bythe area pointed by before using the variable. before using the variable.
Reliability 1.3 Reliability 1.3
a pointer. a pointer. R1.1.2 R1.1.2
const v ariables shall be initializ
const v ariables
ed at
shall
the be
time
initializ
of ed guide
●
at the time of
P ref eren ce P ref eren ce
guide
●
const variables
Compliant ex ample must be initialized
const variables
Compliant ex at the time
ample mustofbedeclaration
initialized as
at values
theex time
N on- compliant cannot
ampleof declaration
beN on-
assigned
as values
toexthem
compliant cannot
sub-
ample be assigned to them sub-
se uently.
const int N If not
= 10; initiali ed,
se0 uently.
const will
int be
N If
=assigned
not initiali
10; for external
ed,const
0 will variables
be N;
int assigned
and the
for values
externalare
const variables
undefined
int N; andfor theau-
values are undefined for au-
tomatic variables, which may tomatic
cause
variables,
unex pected
whichbehavior.
may cause
N oteunexthatpected
missingbehavior.
initialization
N ote atthatdeclaration
missing initialization at declaration
does notvariables
const does notvariables
must be error.
cause a compile initialized
const mustofbedeclaration
at theatime
cause compile initialized as
error. at values
the time of declaration
cannot be assigned as values
to themcannot
sub- be assigned to them sub-
se uently. If not initiali se0 uently.
ed, will be If not initiali
assigned for ed, 0 will
external be assigned
variables and for values
the externalare variables
undefinedandfor
theau-
values are undefined for au-
Note With C++, uninitialized Note With
const is aC++,
compile
uninitialized
error. const is a compile error.
tomatic variables, which may tomatic variables,
cause which
unex pected may cause
behavior. N oteunex
thatpected
missingbehavior. N ote at
initialization thatdeclaration
missing initialization at declaration
does not cause a compile error.
does not cause a compile error.
[Related rules] M1.11.1,[Related rules] M1.11.1, M1.11.3
M1.11.3
Note
Note With C++, uninitialized With
const is aC++, uninitialized
compile error. const is a compile error.
① Q uality concept
uality concepts are related to the main uality characteristics of IS IEC 2 010 . This guide
uses the following four uality concepts
② Practice
escribes the practice to be followed by programmers during coding
- I n outline
- I n detail
③ Rule number
Identification number of each rule
25
④ Rules
Specific reference rule or rules for C language corresponding to the practice that must be
followed. The rules cited from ISRA C are written in the following format.
[ M I SRA C:20 0 4 1.3] , [ M I SRA C:20 12 R8 .14]
⑤ Preference guide
rovides 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.
N o mark :
●
⑥ ule specification
rovides supportive information (verbal indicators) to indicate which rule need to be defined
more specifically in detail or not, depending on the pro ect policy, or should be prescribed in
a document, such as, when it is recommended to record the behavior and usage of compiler-
dependent 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).
N o mark
Choose
Define
《》
D ocument
《》
⑨ Remark s
rovides 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.
27
Terminology U sed in the Practices Chart
The meaning of the terms used in the chart is as respectively explained in the table below
Term M eaning
Access
ype specifier
char int
B oundary alignment
int
L ifetime
M ultibyte character
N ull pointer
N ull character \0
Scope
Side effect
B lock { }
Enumeration type
Enumerator enum
This part presents coding practices for embedded software. As explained carlier, The coding
practices are categori ed according to the perspective of four characteristics ( uality concepts)
reliability , maintainability , portability and efficiency , which have been adopted from
the software uality characteristics defined in IS IEC 2 010. lease note, however, that these
practices have been categori ed 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).
oreover, the coding practices respectively related to these uality 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
M aintainability M
Portability P
Efficiency E
29
Reliability
A large number of embedded software is incorporated into prod-
ucts and used to support our daily liv es in v arious situations. Con-
seq uently, the lev el of reliability demanded to q uite a number of
embedded software is ex tremely high. Software reliability req uires
the software to be capable of not behav ing wrongly ( not causing
failure) , not affecting the functionality of the entire software and
system in case of malfunction, and promptly restoring its normal
behav ior after a malfunction occurs.
At the source code lev el, the point to be noted in regard to soft-
ware reliability is the need of contriv ing methods to av oid coding
that may cause such malfunctions as much as possible.
Various variables are used in programs written in C language. ithout considering the
1
areas to be reserved in the computer and ensuring that these areas are already initiali ed by
the time these variables are used, unexpected malfunctions may occur.
oreover, 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
R1.1.1 Automatic v ariables shall be initializ ed at the time
of declaration, or the initial v alues shall be assigned
●
1
Compliant ex ample N on- compliant ex ample
If automatic variables are not initiali ed, their values become undefined and the operation results may
differ depending on the environment. The initiali ation must be either at the time of declaration or ust
before using the variable.
declaration.
const variables must be initiali ed at the time of declaration as values cannot be assigned to them sub-
se uently. If not initiali ed, 0 will be assigned for external variables and the values are undefined for au-
tomatic variables, which may cause unexpected behavior. ote that missing initiali ation at declaration
does not cause a compile error.
Note ith C , uninitiali ed const is a compile error.
R eliab ility1 ● R 1 n itialize areas an d use th em in con sid eration of th eir size s. 33
Describe initializations
D escribe initializ expressed
ations without without
ex cess or ex
deficiency.
Reliability
elements.
Initiali ing an array with a string will not cause an error at declaration even if a space for a null charac-
ter is not ensured in the array si e. This is not a problem if described intentionally. owever, 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. hen initiali ing a string, it is neces-
sary to ensure a space for the null character at the end. It would be also helpful to refer to STR31-C in
CERT C regarding the points to keep in mind when using the null character.
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 dif-
ferent members and may become the cause of unexpected behavior. To prevent the same value from
being assigned to different members, initiali ation 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.
1.3 ポインタの指す範囲に気を付ける。
Pay attention to the range of the area pointed by a pointer.
Reliability
R1.3.1 ( 1) I nteger addition to or subtraction from ( includ-
ing ++ and --) pointers shall not be made; Array
●
oo e
format with [] shall be used for references and
assignments to the allocated area.
( 2) I nteger addition to or subtraction from ( including ++ and --) point-
1
ers shall be made only when the pointer points to the array and the
result must be pointing within the range of the array.
erforming operations on pointers can blur the destinations pointed by the pointers. It raises the pos-
sibility 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.
or 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.
R eliab ility1 ● R 1 n itialize areas an d use th em in con sid eration of th eir size s. 35
R1.3.2 Subtraction between pointers shall only be applied
Reliability
●
to pointers that address elements of the same array.
【M I SRA C:20 12 R18 .2】
#define N 10 #define N 10
ptrdiff_t off; // ptrdiff_t is a type of result of ptrdiff_t off; // ptrdiff_t is a type of result of
1
In C language, subtraction between pointers expresses how many elements exist between the two ele-
ments pointed by each pointer. In this case, if each pointer points to a different array, the way the vari-
ables 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 program-
mer must ensure that both pointers are addressing elements of the same array.
Reliability
●
when the two pointers are both pointing at either the
elements in the same array or the members of the
same structure.
#define N 10 #define N 10
1
char var1[N]; char var1[N];
char* p = var1; char var2[N];
char* p = var1;
... // Operations performed on p
... // Operations performed on p
if (p < var1+N) { ... } // Compliant
if (p < var2+N) { ... } // Non-compliant
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).
void g(void) {
extern int d[100];
y using restrict type ualifier, efficient code can be generated by a compiler and the accuracy of
static analysis by using such as the code checker will improve. owever, the use of restrict type
ualifier will re uire 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.
R eliab ility1 ● R 1 n itialize areas an d use th em in con sid eration of th eir size s. 37
Reliability
U se data by tak ing their ranges, siz es
2 a n d in t e r n a l r e p r e s e n t a t i o n s in t o
Reliability
consideration.
The data used in programs vary in how they are represented internally and in the range they
can be operated, depending on their types. hen using these different types of data for opera-
tion, they must be written carefully by paying attention to various aspects, including precision
1
and si e. therwise, 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, si es and internal representations, among others, into consideration.
Reliability 2.1
M ak e comparisons that do not depend on internal
representations.
Reliability 2.4
D escribe code by tak ing operation precision into
consideration.
Reliability 2.5
D o not use operations that hav e the risk of information
loss.
Reliability
Make comparisons that do not depend on internal representations.
eliability
2.1 representations.
1
Compliant ex ample N on- compliant ex ample
#define LIMIT 1.0e-4 void func(double d1, double d2) {
void func(double d1, double d2) { if (d1 == d2) {
double diff = d1 - d2; …
if (-LIMIT <= diff && diff <= LIMIT) {
…
In case of a floating-point type, values written in the source code do not exactly match with those actu-
ally implemented. Therefore, the comparison results must be udged by taking account of tolerance.
Reference materials for those wanting to know more in detail about this rule
・ CERT C 00-C
counter.
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, inte-
ger type (int type) should be used for loop counters.
Reference materials for those wanting to know more in detail about this rule
・ CERT C 00-C
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 39
R2.1.3
Reliability
●
memcmp shall not be used to compare structures
and unions.
}; };
struct TAG var1, var2; struct TAG var1, var2;
void func() { void func() {
if (var1.c == var2.c && var1.w == var2.w) { if (memcmp(&var1, &var2, sizeof(var1)) == 0) {
… …
emories for structures and unions may contain unused areas. Since the values in the areas are un-
known, memcmp should not be used. hen making comparisons of structures or unions, they should be
made between the corresponding members.
Reliability
eliability
2.3 comparisons.
Use the same data type to carry out operations or make
1
Compliant ex ample N on- compliant ex ample
nsigned integer operations in C language wrap around without overflow (the result will be the re-
mainder of the maximum representable value). ecause the overflow is not flagged, there is a risk of
not noticing when the operation result differs from the intended result. or 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.
void func(int i1, int i2, long w1) { void func(int i1, int i2, long w1) {
i1 = (i1 > 10) ? i2 : (int)w1; i1 = (i1 > 10) ? i2 : w1;
hen writing code using different types, perform a cast to specify which type is expected as
the result.
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 41
R2.3.3
Reliability
●
L oop counters and v ariables used for comparison
of loop iteration conditions shall be the same type.
sing 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.
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. hen 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 opera-
tion.
Reliability
eliability
parisons of ex pressions mix ed with signed and
unsigned, an ex plicit cast to the ex pected type shall
be performed.
int i; int i;
1
unsigned int ui; unsigned int ui;
void func( ) { void func( ) {
i = i / (int) ui; i = i / ui;
if (i < (int) ui) { if (i < ui) {
... ...
Some operations, such as, si e comparison, multiplication and division output different results, depend-
ing 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 si es. 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 re-
sult can be expected.
N ote: 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.
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 43
信頼性
D o not use operations that hav e the risk of informa-
Reliability
hen 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. hen 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.
hen 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 ade uately accommodate larger values.
N ote: In many cases, it is better to change data types used rather than casting mechanically.
Changing data types should be considered first.
Reliability
●
U nary operator ' -' shall not be used in unsigned
eliability
ex pressions.
1
i = -i; ui = -ui;
If a unary operator - is used in unsigned expression and the operation result falls out of represent-
able value range of the original unsigned type, unintended behavior may occur.
or example, writing if ( - ui < 0 ) in the non-compliant example will not make this if
true.
The result of operation using unsigned char or unsigned short type will be signed int type.
hen the sign bit turns on due to operation, the intended result may not be achieved. This is why cast-
ing to the type of the intended operation is necessary. The above non-compliant example shows that ~uc
always becomes false as it produces a negative value.
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 45
R2.5.4 The right- hand side of a shift operator shall be z ero
Reliability
●
or more, and less than the bit width of the left- hand
side.
b = (unsigned short)a << 12; // Clearly b = a << 12; // There may be an error in the
// indicated that the operation is 16 bits // shift count
The behavior of a shift operator whose right-hand side (shift count) specifies a negative value or a value
e ual to or larger than the bit width at the left-hand side (value to be shifted) is not defined in C lan-
guage standard and will vary depending on the compiler used. ( This bit width will be that of int type
if the si e 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 si e, even though its behavior is de-
fined in the language standard.
[Related rule] . .3
Use types
U se with
types which
that canthe target data
represent thecan be reprenseted.
target data.
he types used for bit field shall be signed int, unsigned int or
_Bool f a bit field of bit idth is re uired unsigned int type or
_Bool type shall be used.
3 he 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 f a bit field of bit idth
is re uired the type that specifies unsigned or _Bool type shall
be used.
1
_Bool m1:1; // Use of char type.
}; // Compliant in (3) if char type
// is allowed by the compiler
Compliant example of (3) enum E m4:2; // Non-compliant:(1)(2)
struct S { // Use of enum type.
unsigned char m1:2; // If char is defined by the
// Compliant in (3) if enum type
// compiler as allowable:
// conpliant // is allowed by the compiler
enum E m2:2; // If enum is defined by the _Bool m5:1; // Non-compliant: Use of _Bool
// compiler as allowable: // type. Compliant in (2),(3)
// conpliant };
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 47
(1) To be compatible with C 0, use only the int type defined in C 0, which is the int type that has
specified the signedness to either signed or unsigned . o not use the signedness-unspecified int
Reliability
type that may become signed or unsigned, depending on the compiler used.
(2) se only the int type that specifies the signedness as signed or unsigned defined in C , or the
_Bool type, and do not use the int type that does not specify the signedness because the interpreta-
tion of signedness or unsignedness may vary depending on the compiler used.
(3) In addition to the types defined in C language specification, the types defined in processing systems
1
can also be used. owever, do not the integer type that does not specify the signedness, because the
interpretation of signedness and unsignedness may vary depending on the compiler. oreover, 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.
The result of bitwise operation ( ~, << , >> , & , ^ , | to signed type may vary, depending on the compiler used.
Reliability
eliability
R2.7.1 ( 1) Pointer type shall not be conv erted to other
pointer type or integer type, and v ice v ersa, with
the ex ception of mutual conv ersion between
“ pointer to data” type and “ pointer to void* ”
1
type.
( 2) Pointer type shall not be conv erted to other pointer type or integer
type with less data width than that of the pointer type, with the ex -
ception of mutual conv ersion between “ pointer to data” type and
“ pointer to void* ” type.
( 3) Pointer type shall not be conv erted to other pointer type or integer
type with less data width than that of the pointer type, with the ex -
ception of mutual conv ersion between “ pointer to data” type and
“ pointer to other data” type, and between “ pointer to data” type
and “ pointer to void* ” type.
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 49
If a pointer type variable is casted or assigned to another pointer type, it is difficult to identify what
Reliability
kind of data is contained in the area the pointer points to. ith some s, 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 neces-
sary. oreover, attention must also be given to the value ranges of int type and pointer type. e sure
to check the specifications of the compiler beforehand, because there may be cases where the si e of the
1
As explained in the rule under R.2.7.1, it is a risk to convert (assign) pointer type variable to other pointer
type more than is necessary, because the intended result may not gained. The rules on pointer conversion
have been organi ed in the form of a table, as shown below.
In the following table, the origin to convert from are listed in the rows, and the destination to convert to
are listed in the columns. indicates that the conversion can be made, and indicates that the conversion
should not be performed.
Reliability
eliability
Conerted to
Pointer to Pointer to P oin t e r t o
Other type
data type function type void type
Pointer to data type × × ○ ×
C o n
Pointer to function type × × × ×
verted
Pointer to void type ○ × - ×
from
1
Other type × × ×
etails (2)
Conerted to
Integrer type
Pointer to P o i n t e r
Pointer to With less data With more data
function t o v oid
data type width than that of width that than of
type type
the pointer type the pointer type
Pointer to data type × × ○ × ○
Pointer to function type × × × × ○
Pointer to void type ○ × - × ○
Con With less data
verted width than that of × × ×
from Integrer the pointer type
type With more data
width that than of ○ ○ ○
the pointer type
etails (3)
Converted to
Pointer to Pointer to P o i n t e r With less data With more data
data type f u n c t i o n t o v o i d width than that of width that than of
type type the pointer type the pointer type
Pointer to data type ○ × ○ × ○
Pointer to function type × × × × ○
Pointer to void type ○ × - × ○
Con With less data
verted width than that of × × ×
from Integrer the pointer type
type With more data
width that than of ○ ○ ○
the pointer type
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 51
R2.7.2 A cast shall not be performed that remov es any
Reliability
e careful when accessing the areas ualified by const or volatile, because they are only for refer-
ence and must not be optimi ed. If a cast that removes any const or volatile ualification from the
type addressed by a pointer is performed, the compiler will not be able to check and detect error descrip-
tions in the program even if there are any, or may perform an unintended optimi ation.
Reliability
eliability
there are no conflicting declarations, usages and defini-
tions.
1
Compliant ex ample N on- compliant ex ample
The declaration int func() does not mean that a function has no parameters. It is an old-styled ( 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 rule] . .3
ithout 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.
ISRA C 2012 prohibits the use of functions defined in <stdarg.h>.
hen defining a variadic function that uses va_list type variable to reference an argument, there is a
need to be careful not to make the va_list type variable an indeterminate value. If you want to learn
more about this warning, SC3 -C in CERT C should serve as a good source of reference.
[Related rule] . .3
Reliability2 ● R 2 U se data in con sideration of ran ges, size s an d in tern al represen tation s. 53
R2.8.3
Reliability
This rule is for preventing the prototype declaration and function definition from becoming inconsistent.
Reliability
behav ior.
It is essential to be consistent with the description on how to handle all the potential errors,
by also taking account of unexpected events that may occur in cases that are even conceived
1
as highly unlikely from the standpoint of program specifications. oreover, writing code in
ways that do not rely on language specifications, such as, explicit indication of operator prece-
dence 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.
R3.7 R3.10 described in ESCR C edition are deleted from C language edition as they are not applicable as C language rules.
aking an extern declaration without specifying the si e of an array will not cause an error. owever, if
the si e is not specified, it may cause problems in checking outside the array range. Therefore, it is bet-
ter to explicitly specify the array si e in its declaration. owever, there are cases where it is better not to
specify the array si e in the declaration, such as, when the si e of the array is determined by the number
of initial values and is not fixed in the declaration.
Reliability
cess array elements shall include the decision to
whether the access is within the range of the array
or not.
1
for (i = 0; i < MAX && var1[i] != 0; i++) { for (i = 0; var1[i] != 0; i++) {
// Even if 0s are not set in the var1 array, // If 0s are not set
// there is no risk of accessing outside the // in the var1 array, there is a risk
// array range // of accessing outside the array range
… …
int a[ 5 ] = { [ 0 ] = 1 }; int b[ ] = { [ 0 ] = 1 };
nless the si e of the array is clearly indicated when defining the array, the largest index among the ele-
ments that will be initiali ed will be determined as the si e. hen a designated initiali er is used, there
are times when it is not clear which index is the largest and should be initiali ed.
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 si e is big,
there is a risk of stack overflow.
・ ehavior that is not defined in C language standard
The behavior when the variable length array si e is not a positive value is not defined in C language
standard.
・ isconceived array si e
int y = 10;
typedef int INTARRAY[y];
y = 20;
INTARRAY z; // Array size of z is 10, and not 20.
CERT C also provides a warning regarding the need to be careful when using the variable length array
type. If you find it inevitable to use the variable length array type, the warning described in ARR32-C
shou
argument.
Reliability
of the space the pointer points to.
Since sizeof(array-type variable) yields the si e of the array, it is sometimes misconceived as
sizeof(pointer-type variable) also yields the si e of the space the pointer points to. ut actually, it
yields the si e of a pointer. The use of this rule will also be helpful, for example, to prevent the program-
mers from writing sizeof(p) by mistake, by misconceiving p in p[0] = 0 to be a type of array
without checking the variable declaration.
The second rule (2) is for preventing the misconception that sizeof(array-type argument) yields the
1
si e of an array.
Since the array-type argument is treated as pointer type, sizeof(array-type argument) yields the si e
of a pointer.
Reference materials for those wanting to know more in detail about this rule
・CERT ARR01-C
・C E- 67
・ ISRA C 2012 Amendment 12.
[Related rules] 3. .3 1. .
if (y != 0) { ans = x/y;
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. therwise, division by ero error may
occur at runtime.
ardware trap or memory corruption will occur when the memory is accessed via a null pointer or a
pointer that points to an invalid memory. They can be prevented, such as, by
(1) Assigning a null pointer to a pointer that has already been used. y making it a rule to find out
where the pointer will point to before it is referenced, you can prevent the memory from being used
after it is freed or from being double freed.
(2) In recent years, some embedded operating systems, such as, A T SAR S, provide a system ser-
vice that checks whether the value of the pointer is valid or not. If such type of S is used, be sure
to always use this system service. y confirming that the value of the pointer is valid before the
memory is accessed through the pointer, you can prevent the memory from being accessed un ustly.
[Related rules] 3. .1 3.3.1
p = malloc(BUFFERSIZE); p = malloc(BUFFERSIZE);
if (p == NULL) { *p = '\0';
// Error handling
}
else {
*p = '\0';
}
hen 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 pro ect-specific rule to clearly indicate the
unnecessity of referencing, such as, by casting to void.
Regarding the rules on standard library errors, CERT C ERR30-C and ERR32-C explain about how to
use errno and ERR33-C provides a list of return values in the library and explains how to handle them
properly. These rules should serve as a good source of reference.
[Related rules] 3. .1 3. . 3. .1 3. .
60 P art2 C odin g P ractices f or E m b edded S of tware: P ractices C h art
R3.3.2
Reliability
The function shall check if there are constraints
on parameters before starting to process.
1
return range_error; ...
// Normal processing }
...
}
hether the constraints on parameters are checked by the function that calls or the function that is called
depends on how the interface is designed. owever, in order to prevent checking from being over-
looked, the same check should be performed in one place. Therefore, the check should be performed by
the function that is called. As another guideline, CERT C also recommends checking at the side that is
called. (See CERT C A I00-C.)
In case the function that is called cannot be changed, such as, when it is in a library, create a wrapper
function.
C allows the specification of the lower limit of array si e by using a static ualifier in an array decla-
ration of a formal parameter. or example, in the following function declaration, the lower limit of ele-
ments of an argument of array a is specified as 3.
y specifying such constraints on parameters, tools like the compiler would uite likely check the re-
strictions applied to arguments.
Since the stack si e used at runtime for recursive calls cannot be predicted, there is a risk of stack over-
flow.
Reliability
to handle cases that do not follow the predefined
conditions when they occur.
1
of the else caluse shall be either one of the follow-
ing:
《 ( i) An ex ception handling process shall be written in the else clause.
ii comment specified by the project shall be ritten in the else
clause.》
// else clause of an if-else if statement where // if-else if statement without the else clause
// the else condition does not normally occur if (var1 == 0) {
if (var1 == 0) { …
… } else if (0 < var1) {
} else if (0 < var1) { …
… }
} else {
// Write an exception handling process
…
}
…
if (var1 == 0) {
…
} else if (0 < var1) {
…
} else {
// NOT REACHED
}
If there is no else clause in an if-else if statement, it is not clear whether the programmer has for-
gotten 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 pro-
gram when an unexpected condition occurs can be specified by writing the else clause as follows
(i) rite the behavior under unexpected conditions in the else condition ( ow program behaves
in case of occurrence of the else condition should be determined.)
r, the program is much easier to understand by ust writing a comment that the else condition does
not occur.
(ii) rite a comment specified by the pro ect such as // NOT REACHED clearly indicating that the
else condition does not occur to express that the else clause has not been forgotten.
clause. 》
// Default clause in a switch statement where // Switch statement without the default clause
// the default condition does not normally occur switch(var1) {
switch(var1) { case 0:
case 0: …
… break;
break; case 1:
case 1: …
… break;
break; }
default:
/* Write an exception handling process */
…
break;
}
…
switch(var1) {
case 0:
…
break;
case 1:
…
break;
default:
// NOT REACHED
break;
}
Reliability
gotten 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) rite the behavior under unexpected conditions in the default condition ( redefine the behavior of
theprogram if by any chance the default condition occurs).
r, the program is much easier to understand by ust writing a comment that the default condition
1
does not occur.
(ii) rite 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.
If the amount of change for the loop counter is not 1, an infinite loop may occur. Therefore, for compari-
son to determine the number of loop iterations, do not use the e uality operators (==, !=). (Instead use
<=, >=, < , > .)
same ex pression.
1
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, com-
pilers 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 ob ect is updated and referenced in a se uence of arguments
or binary operation expressions, the execution result is not guaranteed. Such a problem, where the ex-
ecution result is not guaranteed, is called a side effect problem. o 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);
Reliability
ables shall not be described more than once in a
seq uence of actual arguments or binary operation
ex pressions.
1
extern int G_a; extern int G_a;
x = func1(); x = func1() + func2(); // With side effect
x += func2(); // problem
… …
int func1(void) { int func1(void) {
G_a += 10; G_a += 10;
… …
} }
int func2(void) { int func2(void) {
G_a -= 10; G_a -= 10;
… …
} }
2. 2.
volatile int v; volatile int v;
y = v; f(v, v);
f(y, 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, com-
pilers 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 se uence of arguments or binary operation expressions may not be guaranteed.
Such unsafe descriptions must be avoided.
●
sizeof operator shall not be used in ex pressions
that hav e side effect.
i++; y = sizeof(int[i++]);
y = sizeof(int[i]);
i++;
ntil C 0, the expression in parenthesis of sizeof operator was used only for finding the si e of the
expression type, and was not executed.
Therefore, even when ++ operator like sizeof(i++) was described, i was not incremented. owever,
in C , 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.
Reliability
refreshed by other threads is a mistake. volatile is used for preventing the compiler from optimi ing
the data and does not guarantee indivisibility, etc., in concurrent processing. To guarantee the indivisibil-
ity of a single data, use mutex, etc., as the synchroni ation primitive.
It is preferable to ac uire and release synchroni ation primitives at the same level of abstraction in the
same translation unit.
1
R3.11.2 The bit fields that may be allocated in the same
memory space shall not be accessed by multiple
threads or shall be ex clusiv ely controlled properly.
void func2() {
mtx_lock(&lock); // Compliant: Exclusively
// controlled properly
s.flag2 = 1;
mtx_unlock(&lock);
}
If multiple threads access bit fields allocated in the same memory space, the result of data referenced or
refreshed in the ad acent bit fields may become incorrect. To avoid this problem, allocate the data sepa-
rately in different memory spaces or perform the exclusive control or mutual exclusion properly.
Reference materials for those wanting to know more in detail about this rule
・ CERT C C 32-C
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.
M aintaiability 1.4 rite in a style that clearly specifies the operator pre-
cedence.
1
M aintaiability 1.5 Ex plicitly describe the operations that are lik ely to
cause misunderstanding when they are omitted.
M aintainability
When necessary in case of callback function }
int cbfunc2(int arg1, int);
// In case the callback function types are fixed
// to be int(*)(int,int), the second argument
// is necessary even when it is not used
eclarations (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.
1
owever, when writing a call back function, make it explicit that parameter is not used, by not describ-
ing the name of the parameter to keep the function types consistent.
[Related rules] M1. .1, M . .
ormally, invalidated sections of the code should not be left in the code as it may impair the code read-
ability.
However, if there is a need to invalidate certain sections of the code by commenting them out, set a rule,
for example, to use only comment for commenting out. Any section of the code can also be invali-
dated without using comment out by specifying that section in between #if 0 and endif#.
[Related rules] M1.1 .1, M . .
tions R ule
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*.
Maintainability
// float operation func(1l); // 1l (numeral 1 and letter l) can get
func(1L); // Description of L should be an // confused with 11 (number 11)
// uppercase letter if ( ui < 0x8000) {
if (ui < 0x8000U) { // Explicitly state that it …
// is an unsigned comparison
…
Basically, when there is no suffix, an integer constant will be an int type and a floating constant will be
1
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 neces-
sary 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.
Long strings that extend to multiple lines will become easier to read by describing them as concatena-
tion of multiple string literals.
i_var2 = 0;
break;
}
hen 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. When there will be two branch
directions like in case of the non-compliant example, write the if statement in the way shown below.
1
if (i_var1 == 0) {
i_var2 = 0;
} else {
i_var2 = 1;
}
【Reference materials for those wanting to know more in detail about this rule】
・ ISRA C 2012 R16.2
・CERT C SC20-C
If data types are not described in definitions and declarations of functions or variables, they are inter-
M aintainability
preted as int type. Explicitly specifying data types improves readability. In C language standard,
these descriptions that do not explicitly specify the data types are prohibited and will be detected as error
by the compiler.
[Related rule] M . .1
M 1 . 4 演算の優先順位がわかりやすいように記述する。
W rite in a style that clearly specifies the operator
1
1.4 precedence.
The ob ective 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 ( ) be-
cause the order of precedence may be confusing to beginners.
perator 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
M aintainability
M 1 . 5 関数のアドレス取得の演算や比較演算を省略しない。
Ex plicitly describe operations that may lead to mis-
1.5
1
In C language, if a function name is written alone, it means obtaining the function address, and not call-
ing the function. This means that, for obtaining the function address, there is no need of placing & in
front of the function name. owever, 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). y following the rule to add & when ob-
taining the function address, it will become easier to detect mistakes in function names written as they
are without & and subsequent () .
[Related rule] M1. .
int x = 5; int x = 5;
if (x != 0) { if (x) {
… …
} }
M aintainability
In conditional expressions, when the result of the expression is ero (0), it is treated as false, and non-
zero is treated as true. Therefore, comparative operations may be omitted in conditional expressions.
owever, such description may cause unintended behavior. or this reason, the comparisons should not
be omitted to make the intention of the program explicit. oreover,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.
1
[Related rules] . .1 M1. .1
性
M 1 .6
1.6 領域は 1 つの利用目的に使用する。
U se one area for one purpose.
} s_var; } s_var;
… …
int i; int i;
… …
if (s_var.type == INT) { if (s_var.type == INT) {
s_var.u_var.i_var = 1; s_var.u_var.c_var[0] = 0;
} s_var.u_var.c_var[1] = 0;
… s_var.u_var.c_var[2] = 0;
i = s_var.u_var.i_var; s_var.u_var.c_var[3] = 1;
}
…
i = s_var.u_var.i_var;
nion allows the same memory space to be declared with areas of different si es. owever, 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.
1.7 名前を再使用しない。
D o not reuse names.
M 1 .7
M1.7.1 The rules below shall be followed for name uniq ue-
P ref eren ce
guide
R ule
ness.
M aintainability
4. I dentifiers that define obj ects or functions with ex ternal link age
shall be uniq ue.【M I SRA C:20 12 R5.8 】
5. I dentifiers that define obj ects or functions with internal link age
should be uniq ue.【M I SRA C:20 12 R5.9 】
o identifier in one name space should have the same spelling as
an identifier in another name space ith the e ception of structure
member and union member names.【M I SRA C:20 0 4 5.6】
1
Compliant ex ample N on- compliant ex ample
The program will become easier to read by using uni ue 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. L abel 2.Tag 3. Member of structure or union . ther identifiers
* acro has no name space.
The language specification allows using the same name to different identifiers if their name spaces dif-
fer, but this rule restricts such usage for the purpose of improving the readability of the program.
Redefining names for functions, variables and macros defined in the standard library degrades the read-
ability of the program.
struct S {
int _mem1; // Not reserved, but shall not be
// used
M aintainability
};
1
These names are reserved for variables or functions with file scope and for tag names.
hen the reserved names are redefined, the behavior of the compiler will not be guaranteed.
N ames that start with an underscore and are followed by a lowercase letter are not reserved for use
outside the file scope. ut to make it easy to remember, this rule restricts the use of all names
starting with an underscore.
The right-hand side of && or || operators may not be executed, depending on the result of the condi-
tion 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
1
[Related rules] 3. .1 3. .
acro 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. owever, using macros for these purposes will degrade readability.
It is important to use macros only where coding and modification errors can be avoided. or do-while-
ero, see ISRA C 200 .
urthermore, in CERT C, there is a rule that says, o not conclude macro definitions with a semicolon
( RE11-C). The programmers should also keep this recommendation in mind when defining the macros
since inserting a semicolon at the end of a macro definition may unexpectedly change the control flow of
the program.
#line serves as the means to intentionally modify file names or line numbers of warning or error mes-
sages 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.
M aintainability
guide
Seq uences of three or more characters starting with
R ule
?? and alternativ e tok ens shall not be used.
1
Compliant ex ample N on- compliant ex ample
// this as abc[x)
C language standard defines trigraph se uences 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 se uences
??= ??( ??/ ??) ?? ??< ??! ??> ??-
can be replaced respectively at the beginning of preprocessing with the following corresponding single-
character counterparts
# [ ] { | } ~
The following two-character patterns, known as digraph se uences
< > <: :> : : :
are handled respectively as e uivalent to
{ } [ ] # ##
in the lex ical analysis.
C defines the following macros in the header iso6 6.h
and and_eq bitand bitor compl
not not_e or or_e xor xor_e
as alternative spellings that correspond respectively to the following tokens.
&& &= & | ~ ! != || |= =
Since trigraph se uences and alternative tokens are not fre uently used, many compilers support them as
an optional feature.
// Digits are not aligned for better appearance // Examples of aligning the digits for better
a = 0; // appearance
b = ; a = 000; // Interpreted as zero (0) in octal
c = 100; // notation
b = 010; // Interpreted as eight ( ) and not as
// ten (10) in decimal notation
c = 100; // Interpreted as hundred (100) in
// decimal notation
M aintainability
Constants starting with ero (0) are interpreted as octal. o ero (0) can be added in front of decimal
numbers to align their digits for the purpose of appearance (i.e. ero padding is not allowed).
性
M 1 . 9 特殊な書き方は意図を明示する。
W hen writing in an unconv entional style, ex plicitly
1.9 state its intention.
defined R ule
efine the unified style of writing infinite loops, for example, by selecting from one of the following
・ rite the infinite loops uniformly as for(;;); .
・ rite the infinite loops uniformly as while(1); .
・ se the macro defined for the infinite loop.
M aintainability
性
D o not embed magic numbers.
1.10 マジックナンバーを埋め込まない。
M 1 .1 0
1
R ule
y defining a constant as a macro, its meaning can be stated explicitly. hen 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 rule] M . .
1.11 領域の属性は明示する。
Ex plicitly state the area attributes.
M 1 .1 1
hen a variable is only referenced and not modified, declaring it as const- ualified variable makes
it clear that it is not modified.That is why read-only variables should be const- ualified. oreover, a
memory that is only referenced by the program but modified by other execution units should be declared
with const volatile ualification so that the compiler can check and prevent the program from re-
newing it by mistake. Furthermore, function interfaces can be clearly stated by adding consts to param-
eters when the memory spaces indicated by the parameters are only referenced in function processing.
M aintainability
Areas ualified as volatile prohibit the compiler from optimi ing them. rohibition of optimi ation
means that executable ob ect 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 ualified as volatile , the compiler will normally ig-
nore such statement and will not generate an executable ob ect. hereas, if it is ualified as volatile
, the compiler will generate an executable ob ect that only references variable x (loads it to the register).
This description can be assumed to have meaning in indicating the interface to I registers (mapped to
1
the memory) that are reset when the memory is read. Embedded software has I registers for controlling
hardware that should be ualified as volatile when considered appropriate, based on their characteristics.
M1.11.3 《Rules for v ariable declaration and definition for P ref eren ce
guide
Variables ualified as const can be allocated to R i ation target areas. or example, when developing
a program where R i ation is applied, ualify the read-only variables as const , and specify the name
of the section to which these variables are allocated by, such as, #pragma.
M 1 . 1 2 コンパイルされない文でも正しい記述を行う。
1.12 Correctly describe the statements ev en if they are
not compiled.
#if 0 #if 0
… …
#else #else1
int var; int var;
#endif #endif
#if 0 #if 0
/* I don't know */ I don't know
#endif #endif
1
2 modification errors
ne 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.
M aintainability
M aintaiability 2.1 Clarify the grouping of structured data and block s.
2.1
M2.1.1 I f arrays and structures are initializ ed with v alues
P ref eren ce
guide
other than 0 , their structural form shall be indicated R ule
by using braces ‘ { }’ . D ata shall be described without
any omission, ex cept when all v alues are 0 .
M aintainability
In initiali ation 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 initiali ation are assigned. It is safer to create blocks according to the
structure, and fully describe the data for initialization without omitting any.
1
[Related rules] 1. .1 M . .3
M2.1.2 The body of if, else if, else, while, do, for, and
P ref eren ce
guide
if (x == 1) { if (x == 1)
func(); func();
}
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. owever, 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
In CERT C, there is a rule that says, o not place a semicolon on the same line as an if, for, or while
statement (E 1 -C). y following this recommendation, unexpected insertion of a semicolon, such
as, the following
if (x==b); {
...
}
can be prevented. This kind of code can be detected by using a code checker..
M aintainability
if (x != 0) { // Refer to the value in the if ( x != 0 ) { // Refer to the value in the
// immediately preceding call // immediately preceding call
x++; x++;
} }
… …
} }
void func2(void) void func2(void) {
{ y = 0; // Initialize each time
int y = 0; // Initialize each time …
… }
}
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 ( ithout static,
generally, stack memory is used and is valid until the end of the function.)
・Initiali ation 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 re-
tained 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. hen
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 misunder-
standing that static has been used by mistake).
[Related rule] M . .
… …
if (x == 0) { if (x==0) {
x++; x++;
} }
… …
} }
The fewer the global variables, the higher the readability of the entire program becomes. To prevent the
1
number of global variables from increasing, static storage class specifiers should be used as much as
possible.
[Related rule] M . .
M aintainability
Compliant ex ample N on- compliant ex ample
enum ecountry { #define ENGLAND 0
ENGLAND, FRANCE, #define FRANCE 1
} country; #define SUNDAY 0
enum eweek { #define MONDAY 1
SUNDAY, MONDAY, int country, day;
} day; …
1
… if ( country == ENGLAND ) {
if ( country == ENGLAND ) { if ( day == MONDAY ) {
if ( day == MONDAY ) { if ( country == SUNDAY ) { // It is impossible
if ( country == SUNDAY ) { // It is possible // to check by tools
// to check by tools
To define the constants that are related like a set, use the enumeration type. y defining related constants
as enum type, and using this type, mistakes caused by the use of incorrect values can be prevented.
hile 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.
rom 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
M aintainability
structure through three forms se uence, selection and repetition, is also one of the applicable
techni ues to write simple software programs. riting simple software descriptions through
effective use of software structuring is strongly desired. oreover, 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.
1
M aintainability
{ if (termination condition1) {
Iterated processing 1; break;
if (termination condition1 || termination }
condition2) { if (termination condition1) {
end = 1; break;
} else { }
Iterated processing 2; Iterated processing 2;
} }
}
-or-
for (i=0; loop iteration condition; i++) {
Iterated processing 1;
1
if (termination condition1 || termination
condition2) {
break;
}
Iterated processing 2;
}
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 state-
ment. ( e careful, however, when using an end flag like in the case shown above as compliant example,
because it may complicate the program.)
return err;
}
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 bot-
tom). 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.
or example, goto statement can be useful to make the program simple, such as, when it is used to
ump to error processing or exit from multiple loops. or more information, CERT C E 12-C should
also serve as a good source of reference.
M aintainability
Compliant example of (1) and (2) Non-compliant example of (1) and (2)
switch (week) { // No matter what the value of week is, the
case A: // code will be ELSE ==> bug
code = MON; switch (week) {
break; case A:
case B: code = MON;
code = TUE; case B:
break; code = TUE;
case C: case C:
code = WED; code = WED;
break; default:
1
default: code = ELSE;
code = ELSE; }
break;
} // This This is a case where processing of case
// B is continued after dd++, but it is non-
Compliant example of (2) // compliant not only to (1) but also to (2)
dd = 0; // because there is no comment
switch (status) { dd = 0;
case A: switch (status) {
dd++; case A:
// FALL THROUGH dd++;
case B: case B:
ne 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 state-
ment 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. efine what kind of comment to insert in such case in the coding convention. As one ex-
ample, // FALL THROUGH is a comment that is frequently used.
[Related rule] 3. .
This rule is to prevent the program logic from becoming complex. hen 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.
M aintainability
R ule
than in ex pressions for initializ ing or updating in
for statements.
Compliant example of (1) and (2) Non-compliant example of (1) and (2)
a = 1; a = 1, b = 1;
b = 1;
Non-compliant example of (1)
j = 10; for (i = 0, j = 10; i < 10; i++, j--) {
for (i = 0; i < 10; i++) { …
… }
j--;
}
In general, the use of comma expressions make the program complicated. owever, the progam may
sometimes become easier to understand in expressions for initiali ing and updating in for statements by
using comma expressions to collectively describe all the pre-loop operations as one set and all the loop-
end operations as another set.
x = y = 0; y = (x += 1) + 2;
y = (a++) + (b++);
Assignments include the compound assignments (+= -=, etc) beside the simple assignment (=). ultiple
assignments may be written in one statement, but since they impair readability, one statement should
M aintainability
contain only one assignment.
owever, 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++;
1
性
3.3 目的の違う式は、分離して記述する。
W rite ex pressions that differ in purpose separately.
M 3 .3
In ISRA C 2012, rules 13. and 13.6 in ISRA C 200 have been consolidated into R1 .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 initiali e the loop
counter (C ).
See M3.3.1.
M aintainability
guide
ex pressions to ex amine true or false.
R ule
2 Assignment operators shall not be used in
ex pressions to ex amine true or false, ex cept for
conv entionally used notations.
3.4 複雑なポインタ演算は使用しない。
D o not use complicated pointer operations.
M 3 .4
M aintainability
strptr_t q; strptr_t *q;
Since it is difficult to understand the changes in the pointer values in three or more levels, multiple
pointer indirections impair maintainability.
Recently, developing programs under the shared efforts of multiple programmers has become a
widely accepted approach in software pro ects. 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. oreover, if the naming of variables,
M aintainability
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
pro ect or within the organi ation is often said to be desirable.
1
M aintaiability 4.4
Unify the contents to be described in a file and the
order of describing them.
To make the code easier to read, it is important to unify the coding style applied in the pro ect.
hen defining a new style convention to be followed in the pro ect, the recommended approach would
be to select from already existing coding styles. Existing coding styles have been developed from vari-
ous schools, and many programmers create their programs based on any one or more of these pre-
M aintainability
established styles. ne 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 pro ect, the recommendation would be to define a coding convention that
matches most closely with the current source code.
hat is most important in deciding on the style convention is not in deciding what kind of style to de-
fine, but is in defining a unified style to be followed .
Explained below are the set of style-related items to be defined
1
1 Position of braces ‘ { }’
nify the position to place the braces { }’ so that the beginning and end of a block will become easier
to read (see Representative styles).
2 I ndentation
Indentation makes a group of declarations and operations easier to read. or unified use of indentation,
define the following
Add a space before and after binary and ternary operators, except for the following operators.
[ ], ->, . (period), , (comma operator)
o not add a space between unary operator and its operand.
y applying these rules, coding errors that are attributable to compound assignment operators will be-
come easier to detect.
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. D o 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.
line character shall be placed at an appropriate position. In placing a new line character, the recom-
mended approach is to apply either one of the following two methods. hat is important is to write the
continuation line after indenting.
[ M ethod 1]
[ M ethod 2]
● Representativ e styles
1 K & R style
This is a coding style used in The C rogramming anguage (widely known as R). R used as
the acronym of this book derives from the initials of the two authors. In the R style, the braces { }’
and indentation are placed in the positions described below
Position of braces: lace the braces { } for function definition on the new line at the column
aligned with the beginning of the previous line. lace the braces { }’ for oth-
ers (including structures and control statements, such as, if, for and while) on
the same line without continuing to a new line (see Example of R style).
I ndentation: 1 tab. In the first edition of The C rogramming anguage , the width
of a tab was set to spaces, but in the second edition (A SI compliant),
the number of spaces is set to .
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 S style).
I ndentation: enerally defined as spaces, but is also common.
3 GN U style
M aintainability
This is a coding style for writing packages. It is defined in Coding Standards written by
Richard Stallman and volunteers in the pro ect. In the 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 style).
I ndentation: 2 spaces. Indent 2 spaces for both the braces { }’ and their body.
1
1 Example of &R style 2 Example of BSD style
void func(int arg1) void
{ // Write the { of a function on a func(int arg1)
// new line { // Write the { of a function on a
// Indent is 1 tab // newline
if (arg1) { if (arg1)
… {
} …
… }
} …
}
riting 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 ex amination from
M aintainability
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 de-
scriptions 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 ex tracted from ex isting
coding conventions and related literature.
1
B lock comments
Comments that describe data structures, algorithms, etc., should be in block comment form with the
opening / in column 1, a * in column 2 before each line of comment tex t, and the closing */ in col-
umns 2-3. (N ote that grep ’^.\* ’ will catch all block comments in the file.)
/* Write a comment.
* Write a comment.
*/
Position of comments
B lock comments inside a function
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.
2 GN U coding standards
The following comment rules are described in the Coding Standards
L anguage English.
M aintainability
3 “ The Practices of Programming”
The following comment rules are described in The ractices of rogramming.
Position D escribe comments for functions and global data.
O ther practices
- D on’ t belabor the obvious.
- D on’ t contradict the code.
1
- Clarify, don t confuse
4 O thers
efine the policy on when to use /* */ comment and // comment.
Example 1 se // for the comment at the end of statement, and /* */ for block comment.
Example 2 se only //, because there is a risk of forgetting to close /* */.
Example 3 o not use /* or // within a comment, provided that // may be used within a //
comment.
escribe the copyright notice in the comment.
efine the comment for the switch statements without break.
Example
switch (status) {
case CASE1:
rocessing;
// FALL THROUGH
case CASE2:
・・・
efine the comment for no processing.
Example
if (Condition 1) {
rocessing;
} else if (Condition 2) {
rocessing;
} else {
// NOT REACHED
}
4.3 名前の付け方を統一する。
U nify the naming conv entions.
M 4 .3
O v erall
foo Foo
V ariable and Global
function L ocal
names
M aintainability
O ther
#define MACRO
enum
2 GN U coding standards
D on’ t choose terse names instead, look for names that give useful information about the meaning
1
of the variable or function. ames should be English.
se 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.
O v erall
get_name
enum
4 O thers
hen naming files, variables and other ob ects, use only the following
- etters in the English alphabet (A through and a through )
- igits (0 through )
- Space
M aintainability
- , - .
(See CERT C SC0 -C for related information.)
How to separate a name: A name that consists of multiple words should be either separated with
underscore or delimited using an uppercase letter for the first letters of the
words. etermine which style to adopt.
Hungarian notation: There is a notation called ungarian notation that explicitly indicates the
type of variable.
Ho to name files ive a name with a prefix, for example, that expresses the subsystem.
The validity of file names is also dependent on the environment, such as, the file system. Some file sys-
tems do not allow the use of characters like comma (,) and colon ( ) for file names, while some others
have a special meaning defined for space ( ) and underscore ( ). The programmers need to watch out for
these local restrictions and definitions applied to specific characters to prevent what they write as the file
name using any of these characters from behaving unexpectedly.
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. eader files should contain macro definitions, tag dec-
M aintainability
larations for structures, unions and enumeration types, typedef declarations, external variable declara-
tions and function prototype declarations that are commonly used in multiple source files.
or example, they should be described in the following order
1
4 #define macros
#define function macros
6 typedef definitions (type definitions for basic types such as int or char)
7 enum tag definitions (together with typedef )
struct/union tag definitions (together with typedef)
extern variable declarations
10 unction prototype declarations
11 Inline function
B y using typedef or macro, the readability of the program at first sight can be improved and coding
changes can be locali ed. They should, however, be used according to a specific rule or rules that define
their usage. r else, they may lead to an adverse result, such as, when a different definition is established
for the macro with the same description (making the program more difficult to read or easier to overlook
the coding changes). Therefore, the specific usage of typedef and macros in a pro ect should be de-
fined before starting the pro ect, and such pro ect-specific rule or rules should be consistently followed
throughout the pro ect to mitigate the aforesaid risk of adverse effects.
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.
or example, they should be described in the following order
M aintainability
int func(int in) // are written in the same file and not included
{ // from the header file
… extern int x;
int func (int);
...
int x;
int func (int in) {
...
In C language, variables must either be declared or defined before being used. n the other hand, func-
1
tions can be used without declarations or definitions. owever, to ensure that declarations and defini-
tions are consistent, the declarations should be described in the header file, and that header file should be
included.
cations. R ule
efinitions without initiali ation for external variables can be described more than once. owever, the
behavior is not guaranteed when an external variable is initiali ed in multiple files.
…
}
eader files might be included into several source files. Therfore, describing variable definitions and
function definitions in a header file may unnecessarily enlarge ob ect code si e generated after compila-
tion. asically, only declarations or type definitions should be described in a header file.
1
The descriptive contents of header files should be organi ed to avoid redundant inclusions. owever,
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 han-
dling redundant inclusions
Ex ample of the rule:
#ifndef macro that j udges 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 subse uent in-
clusions. 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 _ ’ .
M aintainability
Compliant ex ample N on- compliant ex ample
1
Compliant example of (2) // declaration
int func1(int x, int y); {
int func2(float x, int y); // rocess the function
}
int func1(int x, int y)
{ typedef int INT;
// rocess the function int func2(float x, INT y) // The type of y is
} // not literally the
// same as in the
int func2(float x, int y) // prototype
{ // declaration
// rocess the function {
} // rocess the function
}
In a function prototype declaration, parameter names can be omitted, but describing appropriate param-
eter names is useful as function interface information. hen 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.
oreover, if the parameter is an array of specific si e, it is desirable to specify the number of its ele-
ments.
Ex ample: void func(int a[4]) { ... }
void func2(size_t n, int arr[n]) { ... } // In case of variable length array
rately. R ule
M4.5.3
M aintainability
2 “ ,” shall not be placed before the last “ }” in the list of initial v alue
ex pressions for structures, unions and arrays, nor in the list of
enumerators. Howev er, placing “ ,” before the last “ }” in the list of
1
The usage of comma in descriptions for initiali ing multiple data is generally divided into two schools of
coding rules. ne school follows the tradition of not placing a comma after the last initial value in order
to indicate the end of initiali ation explicitly. Another school follows the tradition of placing a comma at
the end by considering the easiness of adding or deleting initial values. D ecide on which rule to follow
by weighing the importance of the usage of comma for such descriptions in your specific cases.
In C 0 standard, it was not acceptable to have , ust before }” that indicates the end of an enumera-
tor list, but this became acceptable in C standard.
M4.6.1 1 0 shall be used for the null pointer. NULL shall not
be used in any case.
P ref eren ce
guide
R ule
2 NULL shall be used for the null pointer. NULL shall
not be used for anything other than the null point-
er.
M aintainability
Compliant example of (1) Non-compliant example of (1)
char *p; char *p;
int dat[10]; int dat[10];
p = 0; p = NULL;
dat[0] = 0; dat[0] = NULL;
1
p = NULL; p = 0;
dat[0] = 0; dat[0] = NULL;
NULL has been conventionally used to express the null pointer, but the expression of the null pointer var-
ies, depending on the execution environment. or this reason, some people think that it is safer to use 0.
If the body and parameters of a macro are not enclosed with parentheses ( ) , there is a risk of bug be-
ing 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.
1
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 pro ect-defined
comment to #else or #endif that corresponds with, such as, #ifdef to make their correspondence
easier to understand.
R ule
ready been defined by #if or #elif.
M aintainability
#endif
#if macro name does not determine whether a macro is defined or not. or 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
1
standard, and any other descriptions of defined may cause an error or may be interpreted differently,
depending on the compiler used.
[Related rule] M . .
block 【M
. I SRA C:20 0 4 19 .5】 R ule
[Related rule] M . .
M aintainability
#undef can change the state of #define d macro name to undefined. ut 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 rule] M . .
M aintainability
#if VERSION == 2
…
#if 0 // Invalidated due to ∼
…
In case of #if or #elif controlling expression, true or false is evaluated by the controlling expres-
sion. 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.
1
[Related rule] M . .3
5 easy.
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. oreover, 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.
1
M aintaiability 5.1
W rite in a style that mak es it easy to inv estigate the
causes of problems when they occur.
M5.1.1 《The rules for writing the code for setting debug op-
tions and for recording logs in release modules shall
P ref eren ce
guide
R ule
be defined
esides implementing the specified functionalities correctly, a good program re uires coding that also
takes account of the easiness to debug and investigate into the causes of problems when they occur. e-
scriptions that make investigation of problems easy to conduct can be achieved by writing descriptions
M aintainability
for debugging that are not reflected in the release modules and descriptions for outputting logs after re-
lease 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.
1
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 defi-
nitions and (b) by using assert macros for debugging purpose.
#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_macros.h --
#ifdef DEBUG
#define DEBUG_ RINT(str) fputs(str, stderr)
#else
#define DEBUG_ RINT(str) ((void) 0) // no action
#endif // DEBUG
[Code example]
void func(void) {
DEBUG_ RINT(">> func n");
M aintainability
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.
If the NDEBUG macro is defined at compile time, the assert macro does nothing. O n 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. ote that
the macro name is NDEBUG, not DEBUG.
assert macro is a macro provided by the compiler in <assert.h>. y 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();
}
M aintainability
fined as the coding convention.
1
W hat to output in logs
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.
M acro or function for outputting log information
ocali e the log information output as a macro or a function. It is often preferable to make the
log output destination changeable.
The evaluation order of # operator and ## operator is not defined. Therefore, # and ## operators should
not be mix ed, nor used twice or more.
sing functions rather than function-like macros facilitates tracking processes by stopping at the begin-
M aintainability
5.2 動的なメモリ割り当ての使用に気を付ける。
B e careful when using dynamic memory allocations.
M 5 .2
sing dynamic memory involves the risk of memory corruption caused by invalid memory access 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. The use of dynamic memory should be
avoided, but there are unavoidable cases, such as, when middleware is used, and these cases are, in fact,
not that rare. In case the use of dynamic memory is unavoidable, specific rule or rules, including those
exemplified below, should be established to prevent the aforesaid risks from arising and facilitate the
debugging process
Example 1 rite the code for allocating the memory and freeing the allocated memory symmetrically
in the same translation unit.
Example 2 Assign a new value to the pointer that points to the freed memory.
Since some compilers already provide functions for debug, consider using them as well. pen source
software also has pieces of source code for debug and should serve as useful references when creating
your own.
-- X_MALLOC.h --
M aintainability
#ifdef DEBUG
void *log_malloc(size_t size, char*, char*);
void log_free(void*);
#define X_MALLOC(size) log_malloc(size, __FILE__, __LINE__)
#define X_FREE(p) do {log_free(p, __FILE__, __LINE__); p=NULL;} while(0)
#else
#include <stdlib.h>
#define X_MALLOC(size) malloc(size)
#define X_FREE(p) do {free(p); p=NULL;} while(0)
#endif
[Use of those functions]
1
#include X_MALLOC.h
...
p = X_MALLOC(sizeof(*p) * NUM);
if (p == NULL) {
return (MEM_NOTHING);
}
...
X_FREE(p);
return (O );
[Related rule] 3. .
realloc. Since the behavior after double free is undefined, the behavior of the program that uses
double freed memory is not guaranteed. ne of the methods to prevent this problem from occurring
is to assign a null pointer as the pointer that points to this memory, immediately after freeing this
memory.
The behavior of the program that specifies a null pointer as the argument of free or realloc
function is guaranteed. ouble free can therefore be prevented by making it a rule to assign a null
pointer as the pointer that points to the freed memory,
1
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 ust for check-
ing 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.
Portability 1.4
tion- dependent.
Portability 1.5
W rite in a style that does not depend on the env ironment
used for compiling.
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.
ne 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 stan-
dard, the details are provided in the following related rules.
Portability
P1.1.2 《 ll usage of implementation-defined behavior shall
P ref eren ce
guide
In the language standard, there are implementation-defined items whose behavior varies depending on
the compiler used. or example, the following are implementation-defined and should be documented if
1
they are used.
ow 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
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 re-
quires 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, re-
gardless of the possibility of porting.
性
U se only the characters and escape seq uences de-
P 1 . 2 言語規格で定義されている文字や拡張表記のみを使用する。
1.2 fined in the language standard.
The basic character set defined in the language standard as usable for source code are upper and lower
case letters of the L atin alphabet, decimal digits, graphic characters ( ! “ # % & ‘ ( ) * + , -
. / : ; < = > ? [ \ ] ^ _ { | } ~ ), space character, and control characters that represent the
horizontal tab, vertical tab and form feed. However, a part of these graphic characters varies in countries
and are therefore implementation-dependent. As a result, they may not be correctly processed.
International characters and multibyte characters (like Japanese) can be used as identifiers and charac-
ters, 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.
Portability
As the identifier, only the alphanumeric characters and underscore should be used.
Comments can be written in Japanese. The character code used should be U TF-8. Halfwidth Katakana
shall not be used.
Japanese shall not be used in strings, string constants and file names of #include.
Many compilers these days support U nicode to process multibyte character set that includes Japanese. In
Japan, Shift_ JIS has long and often been used as the character code for processing Japanese characters.
1
B ut recently, there are increasing number of development proj ects using open source that are adopting
U TP-8 as the character code.
The language standard defines the following seven nongraphic characters as escape se uences
P1.3.1 Simple char type ( that does not specify the signed- P ref eren ce
1
guide
ness) shall be used only for storing character v al-
R ule
ues. I f a process that depends on signedness ( im-
plementation-defined is re uired unsigned char or
signed char that specifies its signedness shall be used
Reference materials for those wanting to know more in detail about this rule
・ ISRA C 2012 Rule 10.1
Portability
Compliant ex ample N on- compliant ex ample
// If int is 16bits and long is 32bits // If int is 16bits and long is 32bits
enum largenum { enum largenum {
LARGE = INT_MAX LARGE = INT_MAX+1
}; };
1
In the C language standard, the members of an enumeration type must have values that can be repre-
sented as int type. However, some compilers that support this functionality ex tendedly may not cause
an error even if the value ex ceeds 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.
The following behaviors of bit field vary depending on the compiler used
(1) hether 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) oundary of a bit field in a storage unit
1
If bit fields are used to access data whose bit positions are meaningful, such as, the I 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 | .
R ule
【M I SRA C:20 12 R20 .3】
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-ex pansion of the # include directive.
Most compilers will output an error if it cannot match the format with neither of the two styles, while
Portability
some others may not handle it as an error. Therefore, write the header name format in either of the two
styles to ensure safety.
1
file specification shall be defined R ule
There are two ways of writing include . To unify the writing style, define rules, for example, that in-
clude the following
Specify the header provided by the compiler by enclosing it with < > ;
Specify the header created in the proj ect by enclosing it with “ ” ;
Specify the header provided by the purchased software by enclosing it with “ ” .
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 charac-
ters are used in the following cases, which conse uently 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.
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.
or v ariable. RR ule
ule
Compliant
Compliant ex
ex ample
ample NN on-
on- compliant
compliant ex
ex ample
ample
#define LEN 10 #define LEN 10
... #define INT_SIZE 4
int *p = (int *)malloc(sizeof(int)*LEN); ...
int *p = (int *)malloc(INT_SIZE*LEN);
Since the size of a type or variable varies depending on the complier used, use the sizeof operator to
find out the si e of a type or variable that are implementation-defined.
Portability
1
Portability 2.1 L ocaliz e the code that has a problem with portability.
Portability
1
In C99, inline-specified functions can be written. Many compilers provide ex tended support
to (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
Portability
different behavior depending on the compiler used, thus making it non-portable.
1
by localiz ing them after《defining the macros R ule
The si e and internal representation of integer types and floating point types vary depending on the com-
piler. C specifies the following typedefs to be provided as the language standard. Therefore, these
type definitions should be used. hen using C 0, it is advisable to refer to them as the typedef names
for these basic types.
Si e-specific types int8_t, int16_t, int32_t, int 4_t, uint8_t, uint16_t, uint32_t, uint 4_t
east-width integer types int_least8_t, uint_least8_t, … , int_least 4_t, uint_least 4_t
astest least-width integer types int_fast8_t, uint_fast8_t, … , int_fast 4_t, uint_fast 4_t
aximum-width integer types intmax_t, uintmax_t
Moreover, use size_t for size or length resulting from, such as, the use of sizeof, ptrdiff_t for the
result from pointer subtraction, and wchar_t for wide character.
【Reference materials for those wanting to know more in detail about this rule】
・CERT IN T01-C
Portability
1
D epending on how the source code is written, the obj ect size may increase and the
ex ecution 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
rite in a style that ta es account of resource and
time efficiencies.
Efficiency
1
extern void func1(int,int); // func1: called #define func1(arg1, arg2) // func1: called only
// only once // once
#define func2(arg1, arg2) // func2: called extern void func2(int, int); // func2: called
// many times // many times
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. B ut since inlining is implementation-dependent, inline function may not be ex panded
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 obj ect size because the code will be
spread to wherever the macro function is used.
Efficiency
●
O perations that remain unchanged shall not be per- guide
… …
} }
● 149
Repeating the same process that returns the same result is inefficient. Although optimi ation of the com-
piler is often reliable for preventing such inefficiency, attention is still necessary in some cases, like in
the non-compliant ex ample shown above, where the compiler used cannot determine the invariance..
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.
switch statements often provide higher readability than if statements. In addition, recent compilers
tend to output optimized code using, such as, table j ump or binary search when they process switch
statements. Take these matters into consideration when defining this rule.
Efficiency
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 state-
ments when putting such a branch statement.
cnt = 0;
return;
Automatic variables and formal parameters cannot be referenced after the function return. There-
fore, 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 ex ample are meaningless. If there is a need to return the incremented value to
the caller, the prefix increment must be used.
O verwriting a parameter without referencing its value, as shown in the above ex ample, means that
the value of the argument set by the caller is ignored. This may be a coding error.
if (x == y == z)
The program shown in the above example appears to be a correct description at first sight. ut in
C language, such description is not interpreted mathematically and is treated as a conditional ex pres-
sion 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 ex press. uc can only ex press values
between 0 and 25 5 . ui can never be negative.
The condition shown in the above ex ample compares addresses, and is not a condition for evaluat-
ing whether the string “ abc” is equal to the string pointed by str or not.
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 (function func1). The function that returns a value must not
end the ex ecution with anything other than the return statement (function func2). If a value is not
returned with return, the return value of the function is undefined. In addition, the type of function
with one or more return statements that respectively do not return a value should be void (function
func3). In C99, the inconsistency between such type of function and return statement is detected
as an error by the compiler.
int data[N];
int *p;
p = data;
p += sizeof(data); // p points to 160 bytes ahead and not 40 bytes ahead.
A value for addition or subtraction of integer to or from a pointer variable is automatically scaled
to the size of the type of the obj ect pointed-to. The sizeof operator returns the number of the data
in bytes. Therefore, if the result of sizeof is used as the value for pointer addition or subtraction,
the pointer after the arithmetic may point to an unintended destination.
If the number of data bytes of int type in the above ex ample is 4, sizeof(data) will be 40
( 10). If the result of this sizeof is added to p, which is a pointer that points to int type, the
pointer will point to 160 bytes ( 0 ) ahead, scaling the result of 0 by a factor of prior to the ad-
dition. Pointer p, as a result, will point at an unintended destination.
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.
Ex ample 2: Passing the address of an automatic v ariable to the caller mistak enly
int *func(tag *p) {
int x;
p->mem = &x; // The automatic variable memory area is referenced after the
// function return (risky)
return &x; // The automatic variable memory area is referenced after the
// function return (risky)
}
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 ex ample,
unex pected faults may occur when the area that has been returned to the system is referenced or up-
dated.
The area for compound literal introduced in C99 is freed and may be reused for other purposes
void f ()
{
…
int *p;
{
p = (int []) {2, 4};
…
}
x = p[0]; // The memory area may be referenced after it is freed (risky)
…
}
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.
D epending 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. O r specifying the size of the destination as the copy size
will at least prevent the memory from corrupting.
The above ex ample shows a logical product written mistakenly instead of a logical sum. In C lan-
guage, 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 ref-
erences or updates the array elements to a condition for ensuring that array bounds are not ex ceeded,
This is an example showing that bitwise A operator (&) has been written mistakenly instead
of a logical product operator (&&). The bitwise AN D operator does not mean that the conditions
are processed to gain a logical product. Make sure that the intention of the program is correctly de-
scribed.
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 ex -
pressions to ex amine true or false.”
There are also reverse cases like a==b; where == operator is written mistakenly instead of = op-
erator. Easy mistake like this must also be carefully avoided.
Each compiler has various characteristics of its own. N ote that some compilers do not cause com-
pile errors during compilation even if the program contains inappropriate descriptions.
E ample acro ith the same name that has multiple definitions
// Depending on where AAA is referenced, what is expanded varies
acro name defined by define will not become a compile error in some compilers even when it
is redefined without applying undef beforehand. acro name that may be processed differently de-
pending on where it is used should be avoided since it has the risk of impairing the readability of the
program.
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.
[ eliability ] nitiali e areas and use them by ta ing their si es into consideration
P ractice in detail R ule P age
R 1 .1 U se areas af ter in itializ in g th em . R 1 .1 .1 A utom atic v ariab les sh all b e in itializ ed at th e tim e of 3 3
declaration , or th e in itial v alues sh all b e assign ed j ust
b ef ore usin g th em .
R 1 . 2. 2 - 3 4
m em b er.
R 1 .3 R 1 .3 .1 3 5
R 1 .3 .2 3 6
R 1 .3 .3 3 7
-
structure.
R 1 .3 .4 3 7
【 】
R 2. 1 . 2 3 9
coun ter.
R 2. 1 . 3
un ion s.
ran ge.
R 2. 3 - R 2. 3 . 1 - 4 1
R 2. 3 . 2 - 4 1
R 2. 3 . 3 4 2
R 2. 4 R 2. 4 . 1 4 2
R 2. 4 . 2 4 3
R 2. 5 R 2. 5 . 1 4 4
th e risk of in f orm ation loss.
-
R 2. 5 . 3 - 4 5
R 2. 5 . 4 4 6
m ore, an d less th an th e b it width of th e lef t- h an d side.
R 2. 6 R 2. 6 . 1 4 6
target data.
-
used.
R 2. 6 . 2
R 2. 7 R 2. 7 . 1 4 9
-
【 】
R 2. 7 . 3 5 2
5 3
5 3
of argum en ts.【 】
-
gum en ts,《
》
5 4
th e n um b er of elem en ts.
R 3 .1 .2 - 5 7
R 3 .1 .3 - 5 7
R 3 .1 .4
【 】
R 3 .1 .5
v ariab le.
argum en t.
R 3 . 2. 2
R 3 .3 C h eck th e in terf ace restriction s R 3 .3 .1 I f a f un ction return s error in f orm ation , th en th at error
wh en a f un ction is called. in f orm ation sh all b e tested. 【 】
R 3 .4 R 3 .4 .1 6 2
【 】
in th e else clause. 》
R 3 .5 .3 6 5
R 3 .6 R 3 .6 .1 6 6
ev aluation . -
sion .
M 1 .1 .2 7 3
【 】
《th e codin g
》
M 1 .2 M 1 . 2. 1 - 7 4
-
tion statem en t, b ut v ariab les with in itializ ation an d
v ariab les with out in itializ ation sh all n ot b e m ix ed.
M 1 . 2. 2 7 5
M 1 . 2. 3 7 5
literals sh all b e con caten ated with out usin g n ewlin es
with in th e strin g literal.
of th e switch statem en t.
M 1 .4 - M 1 .4 .1 7 7
M 1 .4 .2 《
》
M 1 .5 M 1 .5 .1
-
【
1 6 .9 】
M 1 .5 .2 7 9
M 1 .6 M 1 .6 .1 7 9
M 1 .6 .2
M 1 .7 D o n ot reuse n am es. M 1 .7 .1 -
n ess.
【 】
【 】
【 】
-
【 】
-
【 】
un ion m em b er n am es. 【 】
M 1 .7 .3
-
sh all n ot con tain side ef f ects. 【 】
m isun derstan din g.
【 】
to m ak e th em n oticeab le.
M 1 .9 .2 《 -
D o n ot em b ed m agic n um b ers.
a m acro.
M 1 .1 1 M 1 .1 1 .1
M 1 .1 1 .2
sh all b e declared as v olatile.
M 1 .1 1 .3 《
M 2. 1 . 2 9 2
statem en ts sh all b e en closed in to b lock s.
M 2. 2. 2 9 4
..
M 2. 2. 3 9 4
M 2. 2. 4 9 5
related con stan ts.
M 3 .1 .2
M 3 .1 .4 9 9
M 3 .1 .5
-
M 3 . 2. 2 -
M 3 .3 M 3 .3 .1 -
【 】
M 3 .3 .2 -
.【 】
M 3 .3 .3
-
-
M 3 .4 M 3 .4 .1
M 4 .2 - M 4 . 2. 1 《
m en ts. com m en ts, f un ction h eader com m en ts, en d of lin e
M 4 .3 .2 《
M 4 .4 M 4 .4 .1 《 1 1 3
-
in g th em .
M 4 .4 .3 1 1 5
-
scrib in g th eir declaration s sh all b e in cluded.
M 4 .4 .4 - 1 1 5
tion s.
M 4 .4 .5 1 1 6
M 4 .4 .6 1 1 6
redun dan t in clusion s. 《
M 4 .5 - M 4 .5 .1 - 1 1 7
tion s.
-
M 4 .5 .2 -
M 4 .5 .3
M 4 .6 - M 4 .6 .1 1 1 9
ers.
M 4 .7 - M 4 .7 .1
cessor directiv es.
M 4 .7 .3 1 21
M 4 .7 .5 1 21
b lock .【 】
M 4 .7 .7 1 23
【
】
M 5 .1 .2 1 27
b e used. 【 】
【 】
M 5 .2 M 5 . 2. 1
《T h e m ax im um
P 1 .1 .3 《its 1 3 4
in terf ace sh all b e docum en ted an d its usage sh all b e
》
P 1 .2 P 1 . 2. 1 1 3 4
P 1 . 2. 2 - 1 3 6
dard sh all b e used.
P 1 .3 P 1 .3 .1 - 1 3 6
- -
P 1 .3 .2 1 3 7
P 1 .3 .3
docum en ted. 【 】
P 1 .4 P 1 .4 .1 - 1 3 9
【 】
P 1 .4 .2 《 1 3 9
P 1 .4 .3
P 1 .5 P 1 .5 .1
P 2. 1 . 2 1 4 3
localiz in g th em af ter《 》.
P 2. 1 . 3 - 1 4 4
E 1 .1 .2 - 1 4 9
E 1 .1 .3
E 1 .1 .4 《
The rules are classified according to the C language grammar shown below.
N o. R ule
on th e gram m ar
1 .1 M 4 .1 .1 《
1 .2 C om m en ts M 4 . 2. 1 《
1 .3 N am in g M 1 .7 .1
【 】
【 】
【 】
un ion m em b er n am es.
M 1 .7 .3
M 4 .3 .2 《
1 .4 M 4 .4 .1 《
M 4 .4 .2 《
M 4 .4 .3
M 4 .4 .5
1 .4 M 4 .4 .6
《
1 .5 C on stan ts M 1 . 2. 2
-
M 1 . 2. 3 -
en ated with out usin g n ewlin es with in th e strin g literal.
1 .6 M 1 .1 .2
sh all n ot b e used.
M 1 .9 .1
2. 1 R 2. 6 . 2
P 1 .3 .1
-
P 2. 1 . 3
《T h e
2. 2 R 2. 1 . 3
M 1 .6 .2
M 1 .7 .2
M 4 .5 .2
2. 3 R 2. 6 . 1
used.
R 3 .1 1 .2
P 1 .3 .3
2. 4 R 1 . 2. 2
M 2. 2. 4
P 1 .3 .2
3 .1 I n itializ ation R 1 .1 .1 A utom atic v ariab les sh all b e in itializ ed at th e tim e of declaration , or th e in itial
v alues sh all b e assign ed j ust b ef ore usin g th em .
3 .1 I n itializ ation R 1 . 2. 1
m atch th e n um b er of th e elem en ts.
R 3 .1 .3
in dicated.
M 2. 1 . 1
M 4 .5 .3 -
3 .2 R 3 .1 1 .1 -
tiv e.
M 1 . 2. 1
2
b e declared in on e declaration statem en t, b ut v ariab les with in itializ ation
an d v ariab les with out in itializ ation sh all n ot b e m ix ed.
M 1 .6 .1
M 1 .1 1 .1
M 1 .1 1 .2 -
tile.
M 1 .1 1 .3 《
M 2. 2. 1
M 2. 2. 2 -
M 4 .4 .4
3 .3
M 2. 2. 3
static.
M 4 .5 .1
3 .4 R 3 .1 .1
-
m en ts.
R 3 .1 .4 【 】
3 .5 M 1 .1 .1
M 1 .3 .3 -
tion s an d v ariab les.
4 .1 F un ction call R 3 .3 .1 I f a f un ction return s error in f orm ation , th en th at error in f orm ation sh all b e
tested 】
R 3 .3 .2
R 3 .4 .1
4 .2 P oin ter R 1 .3 .1
to th e allocated area.
R 1 .3 .2
R 1 .3 .3
sam e structure.
R 2. 7 . 1
R 2. 7 . 3 -
f orm ed.
R 3 . 2. 2
M 3 .4 .1
M 4 .6 .1
4 .3 C ast R 2. 4 . 2
-
f orm ed.
R 2. 7 . 2
4 .4 R 2. 5 . 2
R 3 .1 .5
R 3 .6 .3 th at h av e side ef f ect.
M 1 .5 .1
4 .6 S h if t R 2. 5 . 4
b it width of th e lef t- h an d side.
4 .7 R 2. 1 . 1
R 2. 2. 1
ex am in e true or f alse.
M 1 .5 .2
R 2. 5 . 3
4 .9 M 1 .4 .1
-
f ects.
R 2. 3 . 2
4 .1 1 A ssign m en t R 2. 4 . 1
-
4 .1 1 A ssign m en t R 2. 5 . 1 -
-
M 3 .3 .3
f alse.
《
》
4 . 1 2 C om m a M 3 . 2. 1
-
4 .1 3 R 3 .6 .1
ef f ect
R 3 .6 .2 F un ction calls with side ef f ects an d v olatile v ariab les sh all n ot b e describ ed
-
sion s.
M 1 .4 .2 《
4 .1 4 R 2. 3 . 1
5 . S tatem en t
5 .1 if statem en t R 3 .5 .1 T h e else clause sh all b e written at th e en d of an if - else if statem en t. I f it is
M 1 .3 .1 -
M 3 .1 .4
en d with a b reak statem en t.
5 .3 R 2. 1 . 2
R 2. 3 . 3
R 3 .1 .2
n ot.
R 3 .5 .3 -
M 1 .9 .2 《
M 3 .1 .1
M 3 .3 .1
con trol.
M 3 .3 .2
.
5 .4 M 2. 1 . 2 -
closed in to b lock s.
M 3 .1 .2
6
6 .1 # if related M 4 .7 .2
M 4 .7 .3
M 4 .7 .7
【 】.
6 .2 # in clude P 1 .4 .1
P 1 .4 .2 《
》
P 1 .4 .3
P 1 .5 .1
6 .3 M acro
-
struct.
M 4 .7 .1 -
M 4 .7 .5
1 9 .5
6 .4
M 1 . 1 2. 1 -
cessor.
6 .4 M 5 .1 .2
7 .1 P 1 .1 .1
th e
f un ction alities used an d th eir usage sh all b e docum en ted.
P 1 .1 .2 《
【 】
P 1 . 2. 1
th eir
P 1 . 2. 2
P 1 .5 .2
P 2. 1 . 1 h ow to lo-
P 2. 1 . 2
n in g th e m acros.
7 .2 P erf orm an ce R 1 .3 .4 【 】.
E 1 .1 .1
E 1 .1 .2
E 1 .1 .3 -
eters.
E 1 .1 .4 《
7 .3 - M 5 .1 .1 《
b ug
7 .4 O th er M 5 . 2. 1
C language standard has behaviors that are unspecified or undefined in its language specifications.
(Refer to Column nspecified ehavior and ndefined ehavior below.) Some of the
unspecified behaviors are defined by the compiler, and they are referred to as implementation-defined
behaviors . Every implementation-defined behavior is compiler-specific. In other words, it always
behaves the same way when it is processed by the same type of compiler.
hat this also means is that the behavior may not always be the same when it is processed by a
different type of compiler, even if the code written in the source program is the same. Therefore,
attention is necessary when the program is ported or when the compiler is changed. oreover, if the
programmers are used to working in an environment that only uses a specific type of compiler, they
may incorrectly assume that implementation-defined parts of the code used in their development
pro ect tare all specified in the C language standard and do not consider the possibility of changes
in their implementation-defined behaviors when a different type of compiler is used to process the
program that they write. To prevent them from causing any unexpected errors, it is desirable to check
and keep in mind which behaviors are implementation-defined before starting the programming
process.
Implementation-defined behaviors are normally listed in the manual of each compiler. Some of
the widely-known implementation-defined behaviors are outlined below.
Character codes are a set of values assigned respectively to the characters, symbols, etc. processed
in a computer. Each character coding system has one or more charts that show which character
corresponds to which character code in tabular form. In Table 1, the hori ontal axis of the chart
shows the upper 3-bit and the vertical axis shows the lower -bit. As to which character code system
will be used is implementation-defined. In case of alphabetic character A , for example, upper 3-bit
As you can see, the code used for representing each character varies with each character coding
system. Therefore, close attention is re uired on how the compiler processes the characters when
the character coding system used in the translation environment (environment where the source
program is processed) differs from the character coding system used in the execution environment
(environment where the execution files are processed for operation).
In case of Japanese characters (hiragana, kan i, etc.), a character code composed of 2 bytes or
more is assigned to each character. There are multiple character coding systems that handle Japanese
characters. At present, many personal computers in Japan use the character coding system called
Shift JIS that expresses each Japanese character as a double-byte character. Since the value assigned
to each Japanese character varies with each character coding system, close attention is necessary on
how the compiler handles the Japanese characters.
Another character coding system that began to be widely used in recent years is nicode, which
has been developed to handle the characters of different languages in the world including Japanese
in a unified manner. In nicode, one character may be expressed with 1 byte or multiple bytes (up
to 6 bytes). There are mainly three coding systems in nicode that define the method of expressing
each character (encoding method), which are as follows
1. T - All the characters covered in ASCII are expressed with 1 byte. The rest are expressed in
variable length (from 2 bytes to 6 bytes).
2. T -16 ses 16-bit as a unit to express each character. All the characters are expressed either in
one unit (16-bit) or two units (32-bit).
3. T -32 All the characters are expressed in a fixed length of 32-bit only.
In C11, char16_t (2-byte length) and char32_t ( -byte length) have been added as types that
support wide characters.
The si e of wchar t and the character codes that correspond respectively to wide character types
are implementation-defined. In C11, however, two macros, __STDC_UTF_16__ and __STDC_
UTF_32__ have been introduced, and when these macros are defined, char16_t and char32_t are
encoded respectively according to T -16 and T -32.
eside the behavioral differences expected with the character coding system used, attention is also
necessary, for example, when kan i characters are expressed in Shift JIS. In Shift JIS, each Japanese
character is encoded in two bytes. ut there are some Japanese characters whose second byte is the
same as (back slash or ¥ ) in ASCII. or example, the character code that corresponds to the
kan i character 表 is 0x c in Shift JIS. The second byte 0x c in Shift JIS corresponds to
in ASCII. (See Table 1).
If the compiler used does not support Shift JIS, double-byte characters will be recogni ed as
single-byte characters. In case of double-byte kan i character 表 , it will be processed as escape
se uence since the compiler will recogni e this character as . As a result, the character may be
displayed differently from the intended representation (making it garbled, etc.)
Example
Source code printf(" 表 \n"); // Byte sequence: 0x95 0x5c 0x5c 0x6e
// → 0x5c 0x5c(\\) becomes 0x5c(\).
utput 表n // Byte sequence: 0x95 0x5c 0x6e
// Actually intended to begin a new line after " 表 "
Address with an absolute value is often written in the program for embedded software. A pointer
is used to access a specific address. In the following case, for example, the calculation re uires an
integer to be assigned to a pointer (or vice versa).
The execution code actually used for such conversion between an integer and pointer is
implementation-defined. oreover, the si e of the address value is also implementation-defined.
These behaviors not only depend on the compiler used, but are also largely dependent on the actual
architecture of the processor used for program execution.
The si e resulting after subtraction of two pointers to the element in the same array is not
necessarily guaranteed as the si e (bit length) applied to the address. It is implementation-defined.
C language standard IS IEC 1 defines ptrdiff_t in <stddef.h> as the type of the
result of subtracting two pointers.
hether the signed integer type will be expressed as sign and magnitude representation, ones
complement representation or two s complement representation is implementation-defined.
Therefore, in the following example,
if (( int al & 0x 0000000 ) == 0x 0000000 ) { // if the most significant bit is 1
expected behavior will occur only if the compiler processes the most significant bit of the signed
integer type as representation of the sign bit ( 1 if the value is negative).
oreover, whether the extraordinary value is a trap representation or an ordinary value is also
implementation-defined. Extraordinary value refers to the calculation result that is a value that
does not fit in the si e of the variable. If the variable is unsigned, and the calculation result exceeds
the variable representation range, the actual result in that variable will be the remainder of the
calculation result divided by the maximum representable value of that variable 1. Take an unsigned
-bit variable for example. If the calculated value is 2 7, the remainder of the value 2 7 divided by
2 6 (the maximum representable value of -bit variable 1) that is 1 will be the calculation result.
This behavior is called wrap around .
n the other hand, if the variable is signed, and the calculation result exceeds the variable
representation range, an overflow will occur. In this case, the compiler may either represent the
calculation result in the same way as the case with unsigned variable (as the value left in the
variable) or process it as trap representation, which is a bit pattern specially defined in the system for
internal processing. If the system is using two s complement, the most significant bit of the pattern
defined as trap representation will be 1 and the rest will all be 0.
The so-called embedded C compiler can use the bit field of a si e of unsigned -bit. It is fre uently
used to access the processor registers where bits are assigned to microcontroller functions.
owever, how the bit field is used is implementation-defined. There is no guarantee that a
behavior that was normal with a specific compiler will be the same when a different compiler is
used. oreover, whether the bit se uence will be in the ascending order from 0 set as the most
significant bit or as the least significant bit is also implementation-defined.
urthermore, even when the bit field is used, whether the actual execution code will command bit
access to, such as, internal registers or not is also implementation-defined. The execution code may
command a read-modify-write operation that accesses the byte that includes that bit, and cause an
unexpected failure.
volatile ualifier is used to suppress the optimi ation of the compiler. or example, to wait for
interrupt, there is a code somewhere in the interrupt handler that sets InterruptFlag to 1, as shown
below in the while loop, which does the polling.
while ( InterruptFlag == 0 ) { ; }
In this case, the process to make the variable, InterruptFlag, a value of 1 is not in this loop.
The compiler may optimi e and transform the loop into a simple infinite loop. volatile ualifier
can prevent the compiler from optimi ing in this way.
volatile ualified ob ect implicitly indicates that it may be processed without being recogni ed
by the compiler. ow the execution code configures the access to volatile ualified ob ect is
implementation-defined.
There are various preprocessing directives that are implementation-defined, as outlined below.
• ethod of corresponding each of the header names specified in series by or to either
the header or the name of the external source file
• hether the value of the character constant of the constant e uation that controls the
conditional include matches with the value of the same character constant in the execution
character set
• hether the character constant of a single character of the constant e uation controls the
conditional include takes a negative value or not
• ethod of forming the header name from the preprocessing token in the include directive
(which may also be generated from macro expansion)
• esting limitation when processing #include
• hether is inserted in front of that is the first character of a universal character name
or not when operator is in the character constant or string constant
• ehavior of non-ST C #pragma
rom C (IS IEC 1 ), a specific #pragma directive was defined additionally as a
standard directive in C language. This is called ST C (standard C) #pragma directive .
Any #pragma that is not ST C is implementation-defined.
• ow the __DATE__ and __TIME__ are processed when the translated date and time are not
known.
Even when inline instruction or register ualifier is specified, whether it will be forced or not is
implementation-defined.
To learn about other implementation-defined behaviors that have not been mentioned above, refer
to the manual of the compiler (of the precise version) used in the development.
In C language, there are four kinds of behavior that re uire particular attention.
Unspecified behavior
Undefined behavior
3 mplementation-defined behavior
ocale-specific behavior
( or details, refer to C language standard IS IEC 1 rogramming anguage
C Annex J.)
nspecified behavior and undefined behavior are alike, but do not mean the same, as
explained below.
Unspecified behavior
There are some behaviors that are grammatically correct (and therefore will not be
processed as error) but have alternative execution results depending on which alternative
the compiler chooses to process. These behaviors are collectively referred to as unspecified
behavior . or example, the order of evaluating the actual argument to a function may differ
depending on the choice made by the compiler.
In case of the above code, the result displayed will differ depending on whether i or i++ is
evaluated first. To gain an overall knowledge about what kind of behavior is unspecified, refer
to the list under J.1 in IS IEC 1 . escriptions that will cause unspecified behavior
should be avoided as much as possible.
Undefined behavior
ndefined behavior refers to a set of behaviors that are not defined in C language standard.
or example, the behavior of division by ero is undefined. To gain an overall knowledge
about what kind of behavior is unspecified, refer to the list under J.2 in IS IEC 1 .
Any descriptions that cause undefined behavior must be avoided by all means, since the
behavior resulting from any of such descriptions is not defined in the language standard.
There is a need to know beforehand which undefined behavior can be detected or not by the
static analysis tool that is going to be used for the development.
195
Ci t a t i o n s a n d Re f e r e n c e s
[1] ISO /IEC 25 010:2011, Systems and software enginieering -- Systems and software Q uality Requirements and
Evaluation (SQ uaRE) -- 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 U se of the C L anguage in Vehicle B ased Software” , The Motor Industry Software
Reliability Association, ISB N 0-95 2415 6 -9-0, Apr. 1998, https://www.misra.org.uk
[6 ] “ MISRA-C:2004 Guidelines for the U se of the C L anguage in Critical Systems” , The Motor Industry Software
Reliability Association, ISB N 0-95 2415 6 -2-3, O ct. 2004, https://www.misra.org.uk
[7 ] “ MISRA C:2012 Guidelines for the U se of the C L anguage in Critical Systems” ,March. 2013, ISB N 97 8-1-906 400-
10-1 / Amendment 1, April 2016 / Addendum 2, April 2016 / Technical Corrigendum 1, June 2017 , https://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 Q uestions” , http://www.eskimo.com/~ scs/C-faq/top.html
[10] “ GN U coding standards” , Free Software Foundation, http://www.gnu.org/prep/standards/
[11] “ The C Programming L anguage, Second Edition” , B rian W. Kernighan and D ennis M. Ritchie, ISB N 0-13-11036 2-
8, Prentice Hall PTR, Mar. 1988
[12] “ Writing Solid Code: Microsoft' s Techniques for D eveloping B ug-Free C Programs” , Steve Maguire, ISB N
1-5 5 6 15 -5 5 1-4, Microsoft Press, May. 1993
[13] “ The Practice of Programming” , B rian W. Kernighan and Rob Pike, ISB N 0-201-6 15 86 -X , Addison-Wesley
Professional, Feb. 1999
[14] “ L inux kernel coding style” , http://www.kernel.org/doc/D ocumentation/CodingStyle
[15 ] “ C Style Standards and uidelines efining rogramming Standards for rofessional C rogrammers” , D avid
Straker, ISB N 0-1311-6 898-3, Prentice Hall, Jan. 1992
[16 ] “ C Programming FAQ s:Frequently Asked Q uestions” , Addison-Wesley Professional, N ov. 1995 . ISB N
97 80201845 198, Steve Summit
[17 ] “ C STYL E GU ID E (SO FTWARE EN GIN EERIN G L AB O RATO RY SERIES SEL -94-003)” , N ASA, Aug. 1994,
http://sel.gsfc. nasa.gov/website/documents/online-doc/94-003.pdf
[18] “ The CERT® C Secure Coding Standard” , Robert C. Seacord, ISB N 97 8-03215 6 3217 , Addison-Wesley Professional,
O ct. 2008 (SEI CERT C Coding Standard, 2016 Edition)
196
V er. 1. 0 & V er. 1. 1 A uthors and editors ( in alp habetical order)
AO KI N ao IPA/SEC
EN D O Arisa IPA/SEC
EN D O U Ryuj i Mitsubishi Space Software Co., L td.
FU RU YAMA Hisaki Matsushita Electric Industrial Co., L td.
FU TAGAMI Takao TO YO Corporation
HACHIYA Shouichi GAIA System Solutions Inc.
HAYASHID A Seij i TO SHIB A CO RPO RATIO N
HIRAYAMA Masayuki IPA/SEC
MITSU HASHI Fusako N EC Electronics Corporation
MU RO Shuj i IPA/SEC
N AMIKI Rieko O GIS-RI Co., L td.
O HN O Katsumi IPA/SEC
O HSHIMA Kenj i Ricoh Company, L td.
SHISHID O Fumio eSO L Co., L td.
U ED A N aoko Fuj itsu L imited
U N O Musubi Matsushita Electric Industrial Co., L td.
M arch 28 , 20 1 8
© 20 1 8 , I P A / S E C