Sunteți pe pagina 1din 241

A Guide to Coding Practices for Embedded Software Development [C language edition]

Compiled by the Information-Technology Promotion Agency Japan, Software Engineering Center

(c) 2007, IPA/SEC Permission to copy and distribute this document is hereby granted provided that this notice is retained on all copies, that copies are not altered, and that IPA/SEC is credited when the material is used to form other copyright policies.

(p.ii) Part 1 How to the read coding practices guide.......................................................................................9 1. Overview.......................................................................................................................................10 1.1 What are coding practices?.....................................................................................................10 1.2 Purpose and place of coding practices / Who should use this book.......................................11 1.3 Coding practices characteristics ............................................................................................12 1.4 Notes on using this guide........................................................................................................13 2. How to understand source code quality........................................................................................16 2.1 Quality attribute......................................................................................................................16 2.2 Quality attributes and attitudes toward practices and rules....................................................20 3. How to use this guide....................................................................................................................23 3.1 Situations where this guide is used.........................................................................................23 3.2 Creating new coding conventions...........................................................................................24 3.3 Enhancing existing coding conventions.................................................................................26 3.4 Study material for training programmers and for self study..................................................27 Part 2 Coding practices for embedded software: Chart of practices....................................................28 How to read the chart of practices....................................................................................................29 Terminology in the chart of practices...............................................................................................32 Coding practices for embedded software.........................................................................................32 Reliability..............................................................................................................................................34 Reliability 1: Initialize memory spaces and be mindful of their sizes.............................................35 Reliability 1.1 The memory spaces should be initialized before using them. .............................36 R1.2 Initialization should be described in correct proportion......................................................38 Reliability 1.3 Pay attention to the range that the pointer points to.............................................40 Reliability 2: Pay attention to range, size and internal representation when using data..................44 Reliability 2.1: Make comparisons that do not depend on internal representation. ....................45 Reliability 2.2: Do not evaluate for equivalence to true values...................................................47 Reliability 2.3: Operations and comparisons should be made to data with the same type..........49 Reliability 2.4 Code should be described while taking the operation precision into consideration.................................................................................................................................51 Reliability 2.5: Do not apply operations that have a risk of losing information..........................54 Reliability 2.6 Use types with which target data can be represented. .........................................59 Reliability 2.7: Pay attention to the pointer type. ........................................................................61 Reliability 2.8: Write in the way that the compiler can check if there is no contradiction in declarations, usages and definitions.............................................................................................65 Reliability 3: Write in a way so as to secure the behavior................................................................68

Reliability 3.1: Write code while keeping the size of the memory space in mind.......................69 Reliability 3.2: Divert error cases for operations that may cause errors at runtime. ..................71 Reliability 3.3: Check interface restrictions at function call. ......................................................73 Reliability 3.4: Do not apply recursive calls. ..............................................................................74 Reliability 3.5: Pay attention to branching conditions and code should be described with how to respond when conditions that are not specified occur..................................................................75 Reliability 3.6: Pay attention to the evaluation order...................................................................80 Maintainability......................................................................................................................................83 Maintainability 1: Be aware that other people are reading the program..........................................84 Maintainability 1.1: Do not leave unused descriptions................................................................85 Maintainability 1.2: Do not write in a way that may cause confusion.........................................87 Maintainability 1.3: Do not write in a specialized way................................................................90 Maintainability 1.4: Operations should be described in a way that their priority is clear...........92 Maintainability 1.5: Do not omit operations that obtain function addresses or comparison operations......................................................................................................................................94 Maintainability 1.6 Use a memory space for a sole purpose........................................................96 Maintainability 1.7: Do not reuse names....................................................................................100 Maintainability 1.8: Do not use language specifications that can cause misunderstanding......104 Maintainability 1.9: Clarify your intention when you use specialized writing..........................108 Maintainability 1.10: Do not embed magic numbers.................................................................109 Maintainability 1.11: Cleary state attributes of memory spaces................................................109 Maintainability 1.12: Statements that will not be compiled should also be described correctly. .....................................................................................................................................................112 Maintainability 2: Write in a way so as not to cause modification errors......................................114 Maintainability 2.1 Structured data and blocks should have clear grouping.............................115 Maintainability 2.2 Localize access range and related data.......................................................117 Maintainability 3: Write programs in a simple way.......................................................................122 Maintainability 3.1 Apply structured programming. .................................................................123 Maintainability 3.2 There should be one side effect for one statement.....................................129 Maintainability 3.3 Expressions with different purposes should be described separately.........131 Maintainability 3.4 Avoid using complicated pointer operations...............................................134 Maintainability 4: Write in a unified way.......................................................................................135 Maintainability 4.1 Unify coding styles.....................................................................................136 Maintainability 4.2 Unify how to write comments. ..................................................................141 Maintainability 4.3 Unify naming..............................................................................................143 Maintainability 4.4 Unify contents and their order in files........................................................145

Maintainability 4.5 Unify how to write declarations..................................................................152 Maintainability 4.6 Unify how to write the null pointer.............................................................155 Maintainability 4.7 Unify how to write preprocessing directives..............................................157 Maintainability 5: Write in a way that is easy to test......................................................................163 Maintainability 5.1 Write in a way that is easy to examine the cause of problems. .................163 Maintainability 5.2 Pay attention to usages of dynamic memory allocations. ..........................163 Maintainability 5.1 Write in a way that is easy to examine the cause of problems...................164 Maintainability 5.2 Pay attention to usages of dynamic memory allocations. ..........................168 Portability............................................................................................................................................170 Portability 1: Write in a way that does not rely on the compiler....................................................172 Portability 1.1: Do not use advanced functions or implementation-defined functions..............173 Portability 1.2: Use only characters and escape sequences defined in the language standard. 174 Portability 1.3: Verify and document the data type expressions, advanced functions for operations specifications and implementation-dependent sections............................................177 Portability 1.4: When including source files, check implementation-dependent sections and modify them to be independent..................................................................................................180 Portability 1.5: Write in a way that does not rely on the compilation environment..................181 Portability 2: Localize codes that have portability problems.........................................................183 Portability 2.1: Localize codes that have portability problems..................................................184 Efficiency............................................................................................................................................187 Efficiency1: Write in a way that takes resource and time efficiencies into consideration.............188 Efficiency 1.1: Write in a way that takes resource and time efficiencies into consideration.....189 Part 3 Typical embedded software coding errors ..............................................................................193 Typical embedded software coding errors......................................................................................194 1 Meaningless expressions and statements.................................................................................194 2. Wrong expressions and statements.........................................................................................196 3. Wrong memory usage.............................................................................................................197 4. Errors caused by a misunderstanding of logical operations...................................................199 5. Errors caused by typos............................................................................................................200 6. Descriptions that do not cause errors depending on the compiler..........................................201 Appendix.............................................................................................................................................201 Appendix A: List of practices and rules.........................................................................................202 Appendix B: Rule categorization based on the C language grammar ...........................................217 Appendix C: Implementation-defined functions template.............................................................231 References...........................................................................................................................................239 Authors ...............................................................................................................................................241

Editor...................................................................................................................................................241

(p.iii)

Preface
Publishing notes It has been about a year and half since the Software Engineering Center (SEC, Director: Seishiro Tsuruho) launched with its concept of "let's vitalize the software industry in Japan." During this period of time, when various topics regarding software were gathering public attention, we received much encouragement - ranging from "What do you think you are doing?" to "Keep working hard!" In response to such encouragement, this book is published by the SEC embedded software engineering sector, as the first step to improve embedded software development quality. To achieve such improvement, perfecting the quality at the stage of software implementation, mainly the programming stage, is crucial. This book especially organizes coding Practices that aim for standardizing source codes. It is our desire that this book is used to help many of those engaged in embedded software development. On publishing this book, about ten core members of the Implementation Quality Improvement Technology Committee from the Embedded Software Developing Improvement and Promotion Task Force (chairman: Hiroshi Monden, vice-chairman: Kiichiro Tamaru) organized by the METI (Ministry of Economy, Trade and Industry) and SEC spent about a year and half, or nearly 1000 hours, to develop the draft. This book is the result of members belonging to different companies pooling their expertise and energy, sometimes until late at night. Their efforts are to be acknowledged here. On publication, we would like to express our gratitude to the Shoeisha staff, who readily responded to our editorial demands to achieve a user-friendly product based on the draft by the above committee. It will bring great pleasure to those involved in publishing this book if it can be used to assist embedded software developers. IPA SEC embedded software engineering sector Masayuki Hirayama, Katsumi Ohno

(p.iv)

On publication of the coding practices guide


In recent years, the scale of embedded software has been expanding. This has resulted in a development style that involves many people becoming main stream. In such mass development projects, which involve engineers of various skills, it is crucial to have measures that balances out their differing levels of skill. Especially in the software implementation phase, it is so vital to be able to constantly produce high quality source code that takes security, maintainability and portability into consideration without solely depending on the engineers' skills. This ability is like the fundamental physical strength behind embedded software development. To achieve this, one of the useful methods is to develop and utilize coding conventions, organized based on various experts knowledge of coding. With this background, we have decided to compile the "Coding Practices Guide" targeted for those establishing C language coding conventions. On compilation, the draft was developed by experts familiar with programming techniques from the Implementation Quality Technology Committee from the Embedded Software Developing Improvement and Promotion Task Force constituted by the METI (Ministry of Economy, Trade and Industry) and IPA SEC. This book consists of practices categorized according to quality attributes and corresponding groups of rules. Based on these sets of information, we believe it is possible to establish coding conventions that will match everybody's requirements. We also believe that this book can be used by experienced developers including those engaged in creating coding conventions to overview C language characteristics and to trigger inspiration, and by beginners as a practical textbook to acquire know-how established by past experts. It is our very best wish that this book is effectively utilized to improve embedded software productivity and to realize high-quality software development. March 2006 Embedded Software Development Improvement and Promotion Task Force Implementation Quality Technology Committee

(p.v)

Table of Contents
Preface Part 1 How to read the guide to coding practices 1. Overview 1.1 What are coding practices? 1.2 Purpose and place of coding practices / Who should use this book 1.3 Coding practices characteristics 1.4 Notes on using this guide 2. How to understand source code quality 2.1 Quality attributes 2.2 Quality attributes and attitudes toward practices and rules 3. How to use this guide 3.1 Situations where this guide is used 3.2 Creating new coding conventions 3.3 Enhancing existing coding conventions 3.4 Study material for training programmers and for self study

Part 2 Coding practices for embedded software: Chart of practices - How to read the chart of practices - Terminology in the chart of practices - Coding practices for embedded software Reliability Maintainability Portability Efficiency []

(p.1)

Part 1 How to the read coding practices guide


1. Overview 1.1 What are coding practices? 1.2 Purpose and place of coding practices / Who should use this book 1.3 Coding practices characteristics 1.4 Notes on using this guide 2. How to understand source code quality 2.1 Quality attribute 2.2 Quality attributes and attitudes toward practices and rules 3. How to use this guide 3.1 Situations where this guide is used 3.2 Creating new coding conventions 3.3 Enhancing existing coding conventions 3.4 Study material for training programmers and for self study

(p.2) 1. Overview 1.1 What are coding practices? Creating source codes (code implementation) is an inevitable task for building embedded software. Success or failure in this task greatly affects the quality of the end product. On the other hand, C language, the most popular language for embedded software development, is said to have a high degree of freedom in coding and thus easily reveals the engineers ability. It is undesirable to have a difference in the quality of the source code due to differences in the engineer's skills and experiences. To prevent this situation, some advanced enterprises establish standardize source code coding criteria and conventions to follow as an organization or a group. Problems in coding conventions Normally, coding conventions organize "a way (rule) to write codes to follow so as to maintain quality", but there exists the following issues for coding conventions currently in use. 1) Necessity of rules is not understood. Or the correct method of dealing with rule violations is not understood. 2) There are too many rules to remember. Or there are not enough rules to cover all the important points. 3) No high precision tool to check adherence of rules exists. Checking is done by eyesight giving the engineers extra work. As a result, even with some organizations and departments that have already established coding conventions, a situation exists in which the rules have become a mere facade and are not conformed to. Actually, whether they are conformed to or not, it is still good that there are at least some coding conventions. A worse case scenario is that an organization has not established coding conventions, leaving it up to the individual engineer's decision.

(p.3) What are coding practices? "Coding practices" discussed in this guide are to solve such on-site coding conventions problems. They organize the basic way of thinking (basic concept) to conform to in various coding situations, with software quality in mind. This guide presents these "practices" and related coding conventions samples. Based on the information contained in this book, readers can solve previously stated coding conventions problems by "establishing a particular coding convention for a pertinent department." 1.2 Purpose and place of coding practices / Who should use this book Purpose and position of coding practices This book is a guide for to creators and promoters who develop of coding conventions in associated enterprises and projects. The feature of this guide is that it considers coding conventions as "a way to write codes to follow so as to maintain quality" and organizes the basic concept of rules as practices. The practices are categorized and hierarchized into practice overviews and practice details, based on the quality concept in reference to " ISO/IEC9126-1:2001 Software product quality Part1: Quality model." In addition, rules corresponding to C language are presented for each practice, together with a description of their necessity. The aim is that based on these practices and rules, practical "coding conventions" with intelligible meaning and necessity can easily be created. Who should use this book This guide is written for the following users: Creators of Coding conventions This guide can be used to create new coding conventions or to check and organize existing coding conventions.

(p.4) Programmers and program reviewers Understanding and achieving practices and rules in this guide can help you to easily create highly reliable and maintainable code. Advantages gained By using this guide, the advantages mentioned above can be directly achieved. In addition, as a result the following effects can also be expected. - Diviation of engineers coding skill at the implementation phase, which is a serious

software quality problem , can be corrected - Obvious errors in source codes can be eliminated at early stages such as at the coding phase or following the review

1.3 Coding practices characteristics Coding practices discussed in this guide have the following characteristics. Systematic practices and rules This guide believes that, code quality, like software quality, can be categorized according to quality attributes such as "reliability", "maintainability" or "portability." Thus coding practices and rules are organized systematically based on " ISO/IEC9126-1:2001 Software product quality." In this guide, "practices" are ways of looking at customs and implementation to maintain source code quality and indicate basic concepts behind individual rules. This guide also examined and many existing coding conventions in detail, filtered those that meet the current language specifications ) and presenting them in correspondence to practices. Because practices and rules are categorized based on quality attributes, it is possible to understand which quality they are aiming to maintain. Members involved in writing this guide have used the coding conventions of the enterprises that they belong to as a reference, that is: "MISRA-C", "Indian Hill C Style and Coding Standards", "GNU coding standards." For details, please refer to "References" at the end of the book.

Reference rules that can be used immediately This guide introduces specific C language rules as a reference for creating coding conventions. These rules can be used for coding conventions in their present state. Based on the subsequent "3 how to use this guide", it is possible to easily establish C language coding conventions by selecting the required rules and adding the missing rules. Explanation for necessity of rules In this guide, why certain rules are required is explained through corresponding practices, examples of rules, and remarks. The rules that are obvious for an experienced programmer are mentioned as such in the selection guidelines. Use it as a reference when you are considering if certain rules are required or not. Clear indication of the corresponding relationship with other coding conventions For each rule, this guide indicates the corresponding relationship with existing coding conventions used in general. This makes it easier for you to check inclusive relations. Coding conventions that have correspondence include: "MISRA-C", "Indian Hill C Style and Coding Standards." 1.4 Notes on using this guide Please take note of the following issues when you use this guide. Area covered by the rules In this guide, rules related to the following items are outside the scope of the C language reference rules. - Library functions - Metrics (numbers of lines in functions/complexity etc) - Errors in writing that can be categorized as coding errors

(p.6) While "Errors in writing that can be categorized as coding errors" is excluded from the reference rules normativecoding error examples collected through the compilation of this guide are put together in "Part 3 Examples of coding errors prone to embedded software." These errors are likely to be made by those new to C language. C language beginners are encouraged to read this section as it serves as a useful reference. Some projects may decide to include such coding error-like writing mistakes into rules. In such a case, examples in Part 3 will be a useful reference. Standards quoted and referenced in this guide This guide quotes and references the following standards: C90 A C language standard defined in "JIS X 3010:1996 Programming Language C." It is a 1996 version after "JIS X 3010:1993 Program language C" has been supplemented and corrected. Since the original ISO/IEC 9899:1990 was published in 1990, it is often called "C90." The C language standard has already been modified and is now C99, so C90 is an older standard. However, the common standard at this stage is still C90, and there were not many additions made in the new edition. Thus this guide uses C90 as the language standard. C99 A C language standard defined in "JIS X 3010:2003 Programming Language C" It is the current C language standard. Since the original ISO/IEC 9899:1999 was published in 1999, it is often called "C99." C++ C++ language standard defined in " ISO/IEC 14882:2003 Program language C++." MISRA-C MISRA-C:1998 or MISRA-C:2004. MISRA-C:1998 Conventions in Reference [5] defined by The Motor Industry Software Reliability Association (MISRA) of Britain.

MISRA-C:2004 Conventions in Reference [6] defined by the British MISRA. Revised edition of MISRA-C: 1998.

(p.8) 2. How to understand source code quality 2.1 Quality attribute For many, "software quality" reminds them of "bugs." However, in the field of software engineering, quality of the software product is understood as a broader concept. ISO/IEC9126 organizes this software product quality concept and JIS-X029 is the JIS version of it. ISO/IEC9126-1:2001 and source code quality In ISO/IEC9126-1:2001, six attributes are defined as pertaining to software product quality: "reliability", "maintainability", "portability", "efficiency" "functionality" and "usability." The two attributes "functionality" and "usability" are likely to be included in the upstream design phase. On the other hand, in the implementation phase, the four attributes "reliability", "maintainability", "portability", "efficiency" are deeply involved. Therefore, the practices discussed in this guide apply these four attributes as a major categorization. The table 1 shows the relationship between the JIS X 0129-1 "main quality attribute" and what this guide considers as "code quality", together with a "quality subattribute."

Table 1 Quality attributes of software products in relation to code quality

Quality attributes (ISO/IEC9126-1:2001) Reliability The capability of the software product to maintain a specified level of performance when used under specified conditions.

Quality subattributes (ISO/IEC9126-1:2001) Maturity The capability of the software product to avoid failure as a result of faults in the software. The capability of the software product to maintain a specified level of performance in cases of software faults or of infringement of its specified interface. The capability of the software product to re-establish a specified level of performance and recover the data directly affected in the case of a failure. The capability of the software product to adhere to standards, conventions or regulations relating to reliability. The capability of the software product to be diagnosed for deficiencies or causes of failures in the software, or for the parts to be modified to be identified. The capability of the software product to enable a specified modification to be implemented. The capability of the software product to avoid unexpected effects from modifications of the software. The capability of the software product to enable modified software to be validated. The capability of the software product to adhere to standards or conventions relating to maintainability.

Code quality Not many bugs are discovered through continued use. Tolerance for bugs and interface violations, etc.

Fault tolerance

Recoverability

Reliability compliance

Maintainability

The capability of the software product to be modified. Modifications may include corrections, improvements or adaptation of the software to changes in environment, and in requirements and functional specifications.

Analysability

Ease of understanding the code.

Changeability

Ease of modifying the code.

Stability

Limited impact due to modifications.

Testability

Ease of testing and debugging modified code.

Maintainability compliance

Quality attributes (ISO/IEC9126-1:2001) Portability The capability of the software product to be transferred from one environment to another.

Quality subattributes (ISO/IEC9126-1:2001) Adaptability The capability of the software product to be adapted for different specified environments without applying actions or means other than those provided for this purpose for the software considered. The capability of the software product to be installed in a specified environment. The capability of the software product to co-exist with other independent software in a common environment sharing common resources. The capability of the software product to be used in place of another specified software product for the same purpose in the same environment. The capability of the software product to adhere to standards or conventions relating to portability. The capability of the software product to provide appropriate response and processing times and throughput rates when performing its function, under stated conditions. The capability of the software product to use appropriate amounts and types of resources when the software performs its function under stated conditions. The capability of the software product to adhere to standards or conventions relating to efficiency.

Code quality Ease of adapting to different environments (including conformance to standards).

Installability

Co-existence

Replaceability

Portability compliance

Efficiency

The capability of the software product to provide appropriate performance, relative to the amount of resources used, under stated conditions.

Time behavior

Efficiency with regard to processing time.

Resource utilisation

Efficiency with regard to resources.

Efficiency compliance

Quality attributes (ISO/IEC9126-1:2001) Functionality The capability of the software product to provide functions which meet stated and implied needs when the software is used under specified conditions.

Quality subattributes (ISO/IEC9126-1:2001) Suitability The capability of the software product to provide an appropriate set of functions for specified tasks and user objectives. The capability of the software product to provide the right or agreed results or effects with the needed degree of precision. The capability of the software product to interact with one or more specified systems. The capability of the software product to protect information and data so that unauthorised persons or systems cannot read or modify them and authorised persons or systems are not denied access to them. [ISO/IEC 12207: 1995] The capability of the software product to adhere to standards, conventions or regulations in laws and similar prescriptions relating to functionality. The capability of the software product to enable the user to understand whether the software is suitable, and how it can be used for particular tasks and conditions of use. The capability of the software product to enable the user to learn its application. The capability of the software product to enable the user to operate and control it. The capability of the software product to be attractive to the user. The capability of the software product to adhere to standards, conventions, style guides or regulations relating to usability.

Code quality

Accuracy

Interoperability

Security

Functionality compliance

Usability

The capability of the software product to be understood, learned, used and attractive to the user, when used under specified conditions.

Understandability

Learnability

Operability

Attractiveness

Usability compliance

(p.11) 2.2 Quality attributes and attitudes toward practices and rules Overall structure In this guide, basic matters to be observed when creating source code are organized as "practices." In addition, for an individual "practice", practical issues to pay attention to when writing source code are "rules", each practices are related to particular rules as reference information. This guide categorizes "practices" and "rules" in relation to the four quality attributes shown in 2.1. The meaning of practices and rules in this guide are as follows (See Table 1): Practices Attitudes toward customs and implementations to maintain the source code quality and indicate the basic concept behind individual rules. They are hierarchized into a practice overview and practice details. Rules Specific individual rules to comply to that constitute coding conventions. This guide presents them as references. A group of rules can also be called a rule. Corresponding practices and rules Most practices and rules are related to multiple quality attributes, but they are categorized into the most strongly related attribute. This association with a quality attribute makes it possible for you to understand which practices strongly affect which quality.

(p.12) Quality concept Reliability Maintainability Portability Efficiency

Practice Attitudes toward specific implementation to be complied to improve quality

Practice overviews

Initialize memory Write in a way spaces and wolk that will not inside allocatede depend on space mind their compiler. size when using them.

Take resources and time efficiency into consideration to write code.

Write in a way that avoids errors in case of modification.

Unify writing style

Practice details

Clarify block structure and do not omit breacees for them.

Localize access to data and functions

language Independent (partially dependent) () Rules References of specific coding conventions taking language dependency range into consideration

Block the bodies of if, else if, else, while, do, for, switch statement.

Declare variables within the function if they are used only in that function. .

Make functions called only by functions that are defined within the same file as static functions.

Dependent on language()

Example Create based on reference rules Coding conventions for each project Declare variables within the function if they are used only in that function. Functions called only from functions defined within the same file are static functions. Lines per file are up to 1000. Added independently Figure1: Relationships between quality concepts, practices and rules

(p.13) 3. How to use this guide 3.1 Situations where this guide is used How you should use this book This guide aims to support establishing coding conventions and assumes the following three methods of utilization 1) Creating new coding conventions 2) Enhancing existing coding conventions 3) Study material for training of programmers and for self study Creating new coding conventions If you have not organized coding practices to follow in your organization or department, you can create coding practices suitable for your department based on this guide. Enhancing existing coding conventions Even if your organization or department already has organized coding conventions, it is effective to maintain them regularly. You can use this guide to revise existing coding conventions more effectively. Study material for training of programmers and for self study There are many books written regarding C language. Unlike these existing books, this guide organizes how to create source codes to maintain and improve quality, bringing the viewpoint of quality in implementation to the fore. In this sense, it can serve as perfect teaching material to learn source code qualities from a more practical point of view.

(p.14) 3.2 Creating new coding conventions This section discusses procedures for a project without any coding conventions to create new coding conventions using this book. When to create Coding conventions should be established before the program design phase. While coding conventions are a group of rules to be referenced when coding, some rules are related to program design, such as naming conventions for functions. Therefore, they should be written before the program design phase. How to create It is recommended to establish new coding conventions in the following order: Step-1 Determine a coding conventions establishment strategy Step-2 Select rules based on the establishment strategy Step-3 Define which rules are to be dependent on the project Step-4 Determine procedures for making exceptions when applying rules After this, add rules according to your requirements. Step-1 Determine a coding conventions establishment strategy When you create coding conventions, you must determine a coding convention establishment strategy first. A coding convention establishment strategy is a guideline indicating how codes in a project should be written based on the software the project creates and the characteristics of project members. Examples of strategy include determining to focus on security and avoid at risk features even if they are convenient, or using at risk features with care. When you determine strategies, consider quality attributes you would like to focus in the project as well as the following viewpoints: (p.15) - Coding that takes fail safe into consideration - Coding to make a program easy to view - Coding that takes debugging into consideration Etc..

Step-2 Select rules Based on the establishment strategy determined in Step-1, select rules from the practice charts in Part 2. For example, if you decided to focus on portability, try selecting many rules that fall under the category of portability. "Part 2 Coding practices for embedded software" identifies two type of rules. rules marked as in the "Selection guideline" column. seriously impair the quality attributes that the rule related to if not selected.. On the other hand, the rules marked as are not necessary for those very familiar with language specifications. Use these marks as guides to select rules. The easiest way is to select only those with a "" mark. By doing so, you can select very common rules. Step-3 Define which rules are to be dependent on the project There are three kinds of rules for this guide. 1) Rules that can be used as coding conventions as they are 2) Rules that should be regulated by documentation ("Doc" mark in the Conventions column) 3) Rules that should be selected as to which rule it is to be according to project characteristics (Rules with "Sel" mark in the Selection guidelines column) The rules 2) and 3) cannot be used as they are. If you selected the 2) rules, you need to regulate rules based on "Rule definition guidelines" recorded as a supplement in each practices page. If you selected the 3) rules, select a rule from several rules presented.

(p.16) Step-4 Determine procedures for making exception when applying rules Depending on features required, a quality attribute to focus on at the time of coding may be different (for example, efficiency should be focused on rather than maintainability). Therefore, in such cases, it is possible to cause difficulties such as not achieving initial aims because you are writing according to strictly defined rules. To deal with such a situation, it is necessary to define procedures to allow partial exception of the rules. () What is important is to describe what problems can be caused by writing according to rules and to have experts to review it, recording the results. Do not allow it to be easy to make exceptions so as to prevent the rules from becoming meaningless. The following is an example of a procedure to allow an application exception. [Sample procedure] (1) Write a statement of reason for an application exception. (examples of items in the statement: "rule number", "location (file name, line number)", "problems in abiding by the rule", "effect of not applying the rule") (2) Have experts review it. Add the review results to the statement (3) Gain approval from the manager of the coding phase Record the approval in the statement. 3.3 Enhancing existing coding conventions For projects that have existing coding conventions, this guide can be used as a reference to enhance the coding convention. Preventing missing information Categorizing existing coding conventions based on the practice concept in this guide and of the coverrage., Then you can identify misshinng conventions and renew awareness of what your project coding conventions

(p.17) Clarifying necessities of rules By referring to practices and rule application examples in this guide, you can use this guide as a tool to understand the necessity of rules that you had been forced to apply without knowing why. 3.4 Study material for training programmers and for self study This guide is ideal study material for beginner programmers such as those who have studied C language but are not used to practical coding or do not have much experience. Who should read this book This guide is for the following programmers: - Programmers who have studied C language - Programmers who have experience in other languages but have never used C language What you can learn By reading this guide, categorized from the perspectives of reliability, maintainability and portability, you can learn: - Coding methods for high reliability programs - Coding methods to avoid bugs - Coding methods for programs that are easy to debug and test - Coding methods and their necessity to make programs easy to see for others

Part 2 Coding practices for embedded software: Chart of practices


- How to read the chart of practices - Terminology in the chart of practices - Coding practices for embedded software Reliability Maintainability Portability Efficiency

(p.20) How to read the chart of practices Organization structure of practices Coding practices discussed in Part 2 are categorized according to four attributes (reliability, maintainability, portability, efficiency) out of the software quality attributes. Practice overview Practices deeply related to each attribute are further organized as a practice overview. For example, for maintainability, they are organized into five practice overviews, from "Maintainability 1: Keep readers in mind" to "Maintainability 5: Write so it is easy to test." Practice details Each practice overview organizes multiple practices (practice details) that belong to the practice overview. For example, for the practice overview "Maintainability 3: Write a clear program", there are four practice details: Maintainability 3.1 Apply structured programming. Maintainability 3.2 Make one side effect for one statement. Maintainability 3.3 Expressions with different purposes should be described separately. Maintainability 3.4 Avoid using complicated pointer operations.

Structure of the practice tables Individual practices have a reference table of rules to keep in mind when coding for real. Each column in the table has the following information:

(p.21) 1. Quality concept 2. Practice overview 2. Practice detail 3. Rule number 4. Rule 5. Selection guideline 6. Convention 7. Appropriate example 8. Inappropriate example 9. Remarks 1. Quality concept Quality concepts relative to the main quality attributes of "JIS X 0129-1." This guide uses the following four quality concepts: Reliability Maintainability Portability Efficiency

2. Practices Practices that programmers should comply with when coding. - Overview - Conceptually defines a larger group of practices. Not dependent on languages. - Detail - Describes conceptual practices in detail. Practices to keep in mind more specifically. Like an overview, it is also language independent, but some C language attributes make it more dependent. 3. Rule numbers The rules identification number.

(p.22) 4. Rules Reference rules for C language that correspond to the practice and that should be specifically complied. If a rule in this column is quoted from MISRA-C:2004, it is shown in the following format: Example: [MISRA 1.3] 5. Selection guideline Guidelines to select rules when creating coding conventions using this guide. No mark: Rules that should be selected according to your project characteristics. : Rules that do not need to be included in the convention for those very familiar with language specification (obvious rules for experienced programmers). : Rules that significantly impair a quality attribute if not complied. 6. Convention Indicates if you need to define details for the target rule or not, depending on project strategy. The rules you can use in their present state but you need to create documents (documentation rules), such as "make a document for performance and usage of language specification dependent on compiler", are also indicated in this column. No mark: Those you do not need to define details for nor create documents. Rul: Rules that you need to regulate specific rules according to the project. The parts you need to regulate are specified in << >>. Sel: Selection. There are several rules presented, from which you need to make a selection. The options are indicated using bracketed numbers (such as (1), (2)...) Doc: Rules for which you need to create a document. The parts to create documents are in << >>. 7. Appropriate example Examples of actual source code applying this rule are shown. 8. Inappropriate example Examples of actual source code violating this rule are shown. 9. Remarks Describes C language specification issues to keep in mind, necessity of rules and problems caused by violation of rules.

(p.23) Terminology in the chart of practices This table explains terms used in the chart. Term Access Type specifier Type qualifier Storage class specifier Alignment Trigraph sequence Lifetime Multibyte character Null pointer Null characters File scope Side effect Block Valid range Enumerated type Enumerator Definition Reference of variables and reference including modification. Specifies data type. There are two kinds, those that specify basic types such as char, int or float and those that specify types uniquely defined with typedef by the programmer. Adds specific attributes to types. There are two type qualifiers: const and volatile. Specifies the location where data is stored. There are four specifiers: auto, register, static and exterm. Indicates methods for the compiler to align data into the memory. For example, if int type is 2 bytes, it makes sure that the data is aligned from an even address of the memory, not from an odd address. Sequence of three defined characters, such as '??=', '??/', '??(', for the compiler to interpret into one specific character. ??=', '??/' and '??(' are interpreted as '#', '\' and '[' respectively. Duration of time that reference from the program is guaranteed after a variable is generated. Characters expressed using two or more bytes. Includes double-byte characters such as Chinese or Japanese characters, and Unicode characters. A pointer that is not equivalent to pointers that point to data or functions. A character that indicates the end of a string. Expressed with '\0'. Indicates that the valid range is to the end of the file. Operations that cause changes to the state of the runtime environment Includes the following processes: reference and changes to volatile data, changes to data, changes to files, and function calls that carry out these operations. A range that is surrounded in curly brackets '{' and '}' in data declarations and programs. A range in which you can use variables. Also called a scope. enum type. Constructed with several enumerated members. Members of the enumerated type (enum type).

(p.24) Coding practices for embedded software This part describes coding practices for embedded software. As has been previously introduced, practices are categorized into four attributes aspects (quality concept), reliability, maintainability, portability and efficiency, based on quality attributes (ISO/IEC9126) required for software. However, this categorization is for convenience sake; some practices and rules help improve both reliability and maintainability just by observing them.

This part also explains coding practices relative to each quality attributes and reference rules to realize them. Reliability R Practices to improve reliability of created software are grouped. Main perspectives include: - Reduce problem at the point of use as much as possible Maintainabilit y M - Tolerance to bugs and interface violation. Practices to create source codes that are easy to modify and maintain are grouped. Main perspectives include: - Codes that are easy to understand and modify - Less influence by modification Portability P - Codes that are easy to verify after modification Practices that enable you to port specific software created with an assumption of operating under a certain environment into another environment efficiently and as accurate as possible are grouped. Practices to effectively utilize functions and resources of created software are organized. Main perspectives include: - Coding that takes processing time into consideration - Coding that takes memory size into consideration.

Efficiency

(p.25)

Reliability
Most embedded software is embedded into products and used in various situations in our life. For this reason, extremely reliable embedded software is required. Such software reliability includes: to operate without errors (no malfunctions), to operate without affecting the functionality of the entire software and system at the time of malfunction, and prompt recovery to normal state after a malfunction. At the source code level, what you need to keep in mind regarding software reliability is to avoid as much as possible coding that may cause such malfunctions. Reliability 1: Initialize memory spaces and be mindful of their sizes. Reliability 2: Pay attention to range, size and internal representation when using data. Reliability 3: Write in a way to secure behavior.

(p.26) Reliability 1: Initialize memory spaces and be mindful of their sizes. Programs written in C language use different variables. When you use these variables, you need to consider their memory spaces that should be secured in the computer and ensure initialization of the memory spaces. Otherwise it may cause unexpected malfunction. You should also use C language pointers with the memory space to point to in mind. Extra caution should be paid when you use pointers as it can cause serious problems to the entire system if you use them wrongly. "Reliability 1" consists of the following three practices. Reliability 1.1 The memory spaces should be initialized before using them. Reliability 1.2 Initialization should be described in correct proportion. Reliability 1.3 Pay attention to the range that the pointer points to.

(p.27) Reliability 1.1 The memory spaces should be initialized before using them. R1.1.1 Automatic variables should be initialized at time of declaration or assign initial values just before using them. Selection guidance Convention Appropriate example void func() { int var1 = 0; /* Initialize at declaration */ int i; var1++; /*Assign an initial value just before using it*/ for (i=0; i < 10; i++) { } } Inappropriate example void func() { int var1; var1++; } If you do not initialize automatic variables their values are undefined and operation results will differ depending on behavior and environment. The initialization timing is either at declaration or just before using the variable. R1.1.2 const variables should be initialized at time of declaration. Selection guidance Convention Appropriate example const int N = 10; Inappropriate example const int N;

const variables should be initialized at declaration as you cannot assign values to them later. If you do not initialize them, it will be 0 for external variables and undefined for automatic variables, so it may result in unexpected behavior. Keep in mind that even if it is not initialized at declaration, it will not cause a compile error. Note: With C++, if you do not initialize const, it will be an error.

[Related rules] M1.11.1 M1.11.3

(p.28) R1.2 Initialization should be described in correct proportion. R1.2.1 When you initialize an array with a specified number of elements, you need to match the number of initial values with the number of elements specified. Selection guidance Convention Appropriate example char var[] = "abc"; or char var[4] = "abc"; Inappropriate example char var[3] = "abc"; When you initialize an array with a string, it will not cause an error at declaration even if you do not secure a space for a null character in the array size. This is not a problem if it is intentional, but if the array is used as an argument for a function, such as a string handling function, it is more likely to cause unexpected behaviors because there is no null character indicating the end of the string. When you initialize a string, you should also secure a space for the null character at the end. [Related rules] M2.1.1 R1.2.2 Initialization of enumerated type (enum type) members should be one of the following: not specifying constants at all, specifying all constants, or specifying the first member only. Selection guidance Convention Appropriate example /* E1 to E4 are assigned with different values*/ enum etag { E1=9, E2, E3, E4 };enum etag var1; var1 = E3; /*E3 and E4 in var1 will not be equal*/

if (var1 == E4 ) Inappropriate example /* E3 and E4 are both 11 without intention*/ enum etag { E1, E2=10, E3, E4=11 }; enum etag var1; var1 = E3; /* E3 and E4 are equal so it will be unintentionally true */ if (var1 == E4 ) If you do not specify initial values to members of the enum type, the value of each member will be the value of the last member plus 1 (the value of the first member is 0). If you specify or do not specify an initial value, it is possible to assign the same value unintentionally; it may cause unexpected behavior. It also depends on how you use them, but initialization of members should be either one of not specifying constants at all, specifying all constants, or specifying only the first member to prevent the same value being assigned.

(p.29) Reliability 1.3 Pay attention to the range that the pointer points to. Reliability 1.3.1 (1) You should not make integer additions to or subtractions from (including ++ and --) pointers; use an array format with [] for references and assignments to the secured memory space. (2) Integer addition to or subtraction from (including ++ and --) pointers should be made only when the pointer points to the array and the result should point to within the range of the array. Selection guidance Convention Sel Appropriate example #defi ne N 10 int data[N]; int *p; int i; p = data; i = 1; Appropriate example of (1) and (2) data[i] = 10; /* OK */ data[i+3] = 20; /* OK */ Appropriate example of (2) *(p + 1) = 10; Inappropriate example #defi ne N 10 int data[N]; int *p; p = data; Inappropriate example of (1) *(p + 1) = 10; /* NG */ p += 2; /* NG */ Inappropriate example of (2) *(p+20) = 10; /* NG */ Operations on pointers can make the location that the pointer points to ambiguous. In other

words, the likelihood will be higher for unsecured memory space to be referenced or bugs that write in memory spaces to be embedded. You can create a safer program by using a suffix in an array with the name that points to the beginning of the space. Note that for the rule (2), it is possible to point to the location right after the last element of the array, so long as the elements in the array are not accessed. That is, it conforms to the rule if p+MAX is not used to access the array elements when int arr[MAX], p=arr are set. However, if it is used for accessing the array elements, like *(p+MAX), it is violation of the rule.

(p.30) R1.3.2 Subtractions between pointers should only be used for pointers that are pointing to elements in the same array. Selection guidance Convention Appropriate example int off, var1[10]; int *p1, *p2; p1 = &var1[5]; p2 = &var1[2]; off = p1 - p2; /* OK */ Inappropriate example int var1[10], var2[10], off; int *p1, *p2; p1 = &var1[5]; p2 = &var2[2]; off = p1 - p2; /* NG */ In C language, if you calculate subtractions between pointers, the result shows how many elements exist between the elements the two pointers point to. If each pointer is pointing to different arrays, the compiler determines what variables are laid out between them and the results are not guaranteed. This shows that subtractions between pointers are meaningful only when the pointers are pointing to the same array. Therefore, programmers must ensure that the pointers are pointing to the same array when making subtractions between them. [Related rules] R1.3.3 R1.3.3 Comparisons between pointers should be applied only to pointers pointing to the elements of the same array or members of the same structure. Selection guidance Convention Appropriate example

#defi ne N 10 char var1[N]; void func(int i, int j) { if (&var1[i] < &var1[j]) { Inappropriate example #defi ne N 10 char var1[N]; char var2[N]; void func(int i, int j) { if (&var1[i] < &var2[j]) { Comparing addresses between different variables will not cause a compile error but alignment of the variables depends on the compiler so this comparison is meaningless. In addition, the behavior of such a comparison is not defined (undefined behavior).

[Related rules] R1.3.2 R2.7.3

(p.31) Reliability 2: Pay attention to range, size and internal representation when using data. Various data handled in programs have different internal representations according to their categories and have different ranges to be processed. When you use such different data for operations, and if you do not pay attention to data precision or data size when you code the data, it may result in an unexpected malfunction. Therefore, when you handle data, you need to be aware of its range, size and internal representation. Reliability 2.1: Make comparisons that do not depend on internal representation. Reliability 2.2: Do not compare equivalence with true values. Reliability 2.3: Operations and comparisons should be made to data of the same type. Reliability 2.4: Code should be described while taking the operation precision into consideration. Reliability 2.5: Do not apply operations that have a risk of losing information. Reliability 2.6: Use types with which target data can be represented. Reliability 2.7: Pay attention to the pointer type. Reliability 2.8: Write in the way that the compiler can check if there is no contradiction in declarations, usages and definitions.

(p.32) Reliability 2.1: Make comparisons that do not depend on internal representation. R2.1.1 Do not include equivalence or non-equivalence comparisons in floating-point expressions. Selection guidance Convention Appropriate example #defi ne LIMIT 1.0e-4 void func(double d1, double d2) { double diff = d1-d2; if (-LIMIT <= diff && diff <= LIMIT) { Inappropriate example void func(double d1, double d2) { if (d1 == d2) { For a floating type, values in source codes are not exactly equivalent to actually implemented values; you need to take tolerance into consideration when making comparisons. [Related rules] R2.1.2 R2.1.2 Do not use a floating-point variable as a loop counter. Selection guidance Convention Appropriate example void func() { int i; for (i=0; i < 10; i++) { Inappropriate example

void func() { double d; for (d=0.0; d < 1.0;d += 0.1) { If repetitive operation is made to a floating-point variable as a loop counter, errors accumulate and you may not be able to achieve the intended results. For this reason, you should use the integer type for loop counters. [Related rules] R2.1.1

(p.33) R2.1.3 Do not use memcmp to compare structures and unions. Selection guidance Convention Appropriate example struct { char c; long l; } var1, var2; void func() { if (var1.a == var2.a && var1.b == var2.b) { Inappropriate example struct { char c; long l; } var1, var2; void func() { if (memcmp(&var1, &var2, sizeof(var1)) == 0) { Memories of structures and unions can contain unused memory spaces. What is contained in those memory spaces is unknown, so you should not use memcmp. When making comparisons, you should compare between members. [Related rules] M1.6.2 Reliability 2.2: Do not evaluate for equivalence to true values. R2.2.1 You should not make a comparison to a value defined as true in expressions that examine true and false. Selection guidance Convention

Appropriate example #defi ne FALSE 0 int func1(void) ; /* It may return a value other than 1.*/ void func2() { if (func1() != FALSE) { or if (func1() ) { Inappropriate example #defi ne TRUE 1 int func1(void) ; /* It may return a value other than 1.*/ void func2() { if (func1() == TRUE) { In C language, true is indicated with nonzero values, not necessarily 1. [Related rules] M1.5.2

(p.34) Reliability 2.3: Operations and comparisons should be made to data with the same type. R2.3.1 Unsigned integer constant expressions should be described within the range that can be represented with the result type. Selection guidance Convention Appropriate example #defi ne M 0xffffUL if ((M+1) > M) /* If long is 32 bit, there is no problem even if the bit number of int is different.*/ Inappropriate example #defi ne M 0xffffU if ((M+1) > M) /* The result is different depending on if int is 16 bit or 32 bit. If int is 16 bit, the operation result wraps around and the comparison result will be false. If int is 32 bit, the operation result is within the range of int and the comparison result will be true. */ Unsigned integer operations in C language wrap around without overflowing (it will be the remainder of the maximum represented value). Thus it is possible that you do not realize the operation result is different from what you intented. For example, even with the same constant expression, if it is put into environments with different int bit numbers, the results will be different depending on if the operation results exceed the range that can be represented with their type or not. R2.3.2: For a conditional operator (?: operator), logical expressions should be in parentheses and both return values should be the same type. Selection guidance Convention Appropriate example void func(int i1, int i2, long l1) { i1 = (i1 > 10) ? i2 : (int)l1; Inappropriate example void func(int i1, int i2, long l1) {

i1 = (i1 > 10) ? i2 : l1; When you write codes using different types, you need to cast the types to specify which type is expected for the results. [Related rules] M1.4.1

(p.35) R2.3.3 Use the same type of variables for comparison of the loop counter and the loop iteration condition. Selection guidance Convention Appropriate example void func(int arg) { int i; for (i = 0; i < arg; i++) { Inappropriate example void func(int arg) { unsigned char i; for (i = 0; i < arg; i++) { When you use the comparison of variables for the loop iteration condition and if these variables have different ranges of values that they can express, you may achieve unexpected results and it may end up with an infinite loop. Reliability 2.4 Code should be described while taking the operation precision into consideration. R2.4.1 When the operation type and the assignment designation type of the operation result are different, cast them to the type of operation precision expected first and then execute the operation. Selection guidance Convention Appropriate example int i1, i2; long l; double d; void func() { d = (double)i1 / (double)i2; /* Division using type float */ l = ((long)i1) << i2; /* Shifting using long */ Inappropriate example int i1, i2;

long l; double d; void func() { d = i1 / i2; /* Division using type integer */ l = i1 << i2; /* Shifting using int */ The type of operation is determined by the expression (operand) used for the operation and the type of the assignment designation is not considered. If the types of the operation and assignment designation are different, the program may wrongly be expecting you to operate in the type of assignment designation. If you want to execute the operation in a different type from the operand, you first need to cast it into the expected type before executing the operation. [Related rules] R2.5.1

(p.36) R2.4.2 When you make arithmetic operations or comparisons that are mixed with signed and unsigned expressions, you should explicitly cast types into the expected type. Selection guidance Convention Appropriate example long l; unsigned int ui; void func() { l = l / (long)ui; or l = (unsigned int)l / ui; if (l < (long)ui) { or if ((unsigned int)l < ui) { Inappropriate example long l; unsigned int ui; void func() { l = l / ui; if (l < ui) { Some operations have different results depending on if operations, such as size comparison or multiplications and divisions, are calculated with signed or unsigned. If you mix signed and unsigned, which to use is determined based on each data size; unsigned is not always used. Thus, if you apply mixed arithmetic operations, you should check if expected operation is signed or unsigned and explicitly cast the types to achieve expected operation. Note: It is often the case that it is better to change data types used rather than casting mechanically, so you should consider changing data types first.

(p.37) Reliability 2.5: Do not apply operations that have a risk of losing information. R2.5.1 When you assign (=operation, passing arguments in function calls, function return) or operate to data types that may cause information loss, you should check the existence of problems and describe casting to clearly indicate that there is no problem. Selection guidance Convention Appropriate example /* Assignment example */ short s; long l; void func() { s = (short)l; s = (short)(s+1); } /* Operation example */ unsigned int var1, var2; /* int size is 16 bit */ var1 = 0x8000; var2 = 0x8000; if ( (long)var1 + var2 > 0xffff ) { /* The result is true */ Inappropriate example /* Assignment example */ short s; long l; void func() { s = l; s = s+1; } /* Operation example */ unsigned int var1, var2; /* int size is 16 bit */ var1 = 0x8000; var2 = 0x8000; if (var1 + var2 > 0xffff ) { /* The result is false */ If you assign a value to a variable with different type, the value may change (the /* 16 bit */ /* 32 bit */ /* 16 bit */ /* 32 bit */

information is lost). If possible, it is better to assign to the same type. If you assign to different types intentionally, for example you are sure that no information will be lost or you do not care if information is lost, you need to state casting to express that intention. For operation, if the operation result exceeds the range that can be expressed with its type, it may result in unexpected value. For safety, before executing operation, you should first verify that the operation result is within the range that can be expressed with its type. Alternatively, you should convert the type into one that can process larger values. Note: It is often the case that it is better to change data types used rather than casting mechanically, so you should consider changing data types first. [Related rules] R2.4.1

(p.38) R2.5.2: Do not use the unary operator ('-') in unsigned expressions. Selection guidance Convention Appropriate example int i; void func() { i = -i; Inappropriate example unsigned int ui; void func() { ui = -ui; By using the unary operator ('-') in unsigned expressions, if the operation result is outside the range that can be represented with the original unsigned type, you may get unexpected behavior. R2.5.3 When you apply bit complement (~) or left shift (<<) to data in unsigned char type or unsigned short type, you need to explicitly cast types to the type of the result. Selection guidance Convention Appropriate example unsigned char uc; void func() { uc = (unsigned char)(~uc) >> 1; Inappropriate example unsigned char uc; void func() { uc = (~uc) >> 1; The operation result of unsigned char or unsigned short is signed int. If the operation turns the sign bit on, the intended result may not be achieved. Thus you should explicitly cast types to the expected operation type.

[Related rules] R2.5.4

(p.39) R2.5.4 Right-hand side of the shift operator should be zero or more and less than the bit width of the left-hand side. Selection guidance Convention Appropriate example unsigned char a; /* 8 bit */ unsigned short b; /* 16 bit */ b = (unsigned short)a << 12; /* Operation as 16 bit is made clear */ Inappropriate example unsigned char a; /* 8 bit */ unsigned short b; /* 16 bit */ b = a << 12; /* There may be an error in the shift number */ The behavior is not defined in the C language standard for the situation, but it depends on the compiler, when the specified right-hand side of the shift operator (how many bits to shift) is either negative or bigger than the bit width of the shifted value on the left-hand side (if the size is smaller than int, bit width of int) The language standard defines the behavior of specifying a value up to the bit width of int as the number of bit to shift if the type of the left-hand side (shifted value) is smaller than int, but the intention is not clear. [Related rules] R2.5.3

(p.40) Reliability 2.6 Use types with which target data can be represented. R2.6.1 Limit types used for bit-fields only to signed int and unsigned int. If a bit-field of one bit width is required you should use unsigned int type, not signed. Selection guidance Convention Appropriate example struct S { signed int m1:2; unsigned int m2:1; unsigned int m3:4; }; Inappropriate example struct S { int m1:2; /* Signed or unsigned is not specified */ signed int m2:1; /* Signed and lbit */ char m3:4; /* Type other than int */ }; If int is not specified with signed or unsigned and is used for a bit-field, the compiler determines if it is used signed or unsigned. Therefore, int type that is not specified with signed or unsigned should not be used for bit-fields. In addition, using types char, short, long for bit-fields is outside the language standard. So even if the compiler supports it do not use them if you are concerned with portability. Values that can be represented by a bitfield of one bit signed int are only -1 and 0; use unsigned int for a one-bit bit-field. [Related rules] R1.3.3 R2.6.2 Data used as a bit sequence should be defined with unsigned type, not signed. Selection guidance Convention Appropriate example unsigned int fl ags;

void set_x_on() { flags |= 0x01; Inappropriate example signed int fl ags; void set_x_on() { flags |= 1; Results of bitwise operations (-, <<, >>, &, ^, |) to signed type may differ depending on the compiler.

(p.41) Reliability 2.7: Pay attention to the pointer type. R2.7.1 (1) Pointer types should not be converted to other pointer types or integer types and vice versa. However, conversion between the void* type for the pointer type to data is an exception. (2) Pointer types should not be converted to other pointer types or int types less than the data width of the pointer type. However, conversion between the void* type for the pointer type to data is an exception. (3) Pointer types for data can be converted to pointer types of another data type, but pointers to function type should not be converted to pointer types for other function types or data types. When you convert a pointer type to the integer type, you should not convert to an integer type that is less than the data width of the pointer type. Selection guidance Convention Sel Appropriate example int *ip; int (*fp)(void) ; char *cp; int i; void *vp; Appropriate example of (1) ip = (int*)vp; Appropriate example of (2) i = (int)ip; Appropriate example of (3) i = (int)fp; cp = (char*)ip; Inappropriate example int *ip; int (*fp)(void) ; char c; char *cp; Inappropriate example of (1) ip = (int*)cp;

Inappropriate example of (2) c =(char) ip; Inappropriate example of (3) ip =(int*) fp; If you cast or assign a pointer type variable into another pointer type, it makes ambiguous what data is contained in the memory space the pointer points to. With some CPUs, runtime errors occur if you use pointers that do not point to word boundaries and access the destination with int type. Thus by changing pointer types you are creating a risk of unexpected bugs. It is safe not to cast or assign pointer type variables to other pointer types. Converting pointer type to integer type also has a similar risk as the problem stated above. If you need to do this operation, review it with experts. In addition, you should also pay attention to the value ranges that the int type and pointer type process. It is possible that the int type size is 32 bit while the pointer size is 64 bit; confirm the compiler specification beforehand.

(p.42) R2.7.2 A cast shall not be performed that removes any const or volatile qualification from the type addressed by a pointer. [Undefined 39, 40] [MISRA 11.5] Selection guidance Convention Appropriate example void func(const char *); const char *str; void x() { func(str); } Inappropriate example void func(char *); const char *str; void x() { func((char*)str); } Memory spaces qualified by const or volatile can be spaces only for reference or spaces that should not be optimized, so be careful when you access them. If you apply casting to remove const or volatile for pointers pointing to these memory spaces, the above issues become invisible and the compiler is no longer able to check any errors in the program. R2.7.3 Do not examine if pointers are negative or not. Selection guidance Convention Good Appropriate example of application Bad Inappropriate example of application int * func1() { return -1;

}int func2() { if (func1() < 0) { /* Attempt to compare if negative or not */ } return 0; } You need to keep in mind that comparison( comparison ) between pointers and 0 is meaningless. If 0 is compared to a pointer, it is converted to a null pointer by the compiler. Therefore, although it may seem to be comparing if the pointer is negative or not, it is actually a comparison between pointers and the resulting behavior may different from programmers expectation. [Related rules] R1.3.3

(p.43) Reliability 2.8: Write in the way that the compiler can check if there is no contradiction in declarations, usages and definitions. R2.8.1 Functions without argument should be declared with the argument type as void. Selection guidance Convention Appropriate example int func(void) ; Inappropriate example int func(); int func(); is not a declaration of a function without an argument, but it is an old declaration meaning that the number and type for the argument is unknown. You should specify void when you declare a function without an argument. [Related rules] R2.8.3 R2.8.2 (1) Functions shall not be defined with a variable member of arguments. [Unspecified 15; Undefined 25, 45, 61, 70-76] [MISRA 16.1] (2) If you use functions with variable arguments <<you should document behavior in implementation>>. Selection guidance Convention Sel Doc Appropriate example Appropriate example of (1) int func( int a, char b); Inappropriate example Inappropriate example of (1) int func( int a, char b, ... ); You should understand how variable argument functions behave in their implementations if you want to use them. Otherwise it may result in unexpected behavior.

In addition, when you specify arguments as variable, the number and type of the argument are not clearly defined, so readability will deteriorate. [Related rules] R2.8.3

(p.44) R2.8.3 Prototype declarations should be made before function calls and function definitions. In addition, make sure that function calls and definitions refer to the same declaration. Selection guidance Convention Appropriate example -- fi le1.h -void f(int i); -- fi le1.c -#include "fi le1.h" void f(int i) { } -- fi le2.c -#include "fi le1.h" void g(void) { f(10); } Inappropriate example -- fi le1.c -void f(int i); /* Declaring it in each file */ void f(int i) { } -- fi le2.c -void f(int i); /* Declaring it in each file */ void g(void) { f(10); } Function declarations take two formats: the K&R format and the function prototype format. With the K&R format, the compiler cannot check the argument type of the function, so it is difficult to locate programming errors. Therefore, use the function prototype declaration. Avoid mixing the prototype and K&R formats for definition and declaration of one function, as it can result in unexpected problems. [Related rules] R2.8.1 R2.8.2

(p.45) Reliability 3: Write in a way so as to secure the behavior. In program specifications, it is necessary to thoroughly define how to process errors even for impossible cases, in consideration of unexpected situations. In addition, coding that does not rely on the language specifications such as establishing the operators priority can improve security. To realize high reliability, it is desirable to avoid coding that may lead to malfunction and write securely insuring the behavior as much as possible. Reliability 3.1: Write code while keeping the size of the memory space in mind. Reliability 3.2: Divert error cases for operations that may cause an error at runtime. Reliability 3.3: Check interface restrictions at function call. Reliability 3.4: Do not apply recursive calls. Reliability 3.5: Pay attention to branching conditions and code should be described with how to respond when conditions that are not specified occur. Reliability 3.6: Pay attention to the evaluation order.

(p.46) Reliability 3.1: Write code while keeping the size of the memory space in mind. R3.1.1 (1) Ensure to specify the number of elements in the extern declaration of the array. (2) Ensure to specify the number of elements in the extern declaration of the array, except for the extern declaration of arrays corresponding to an array definition with initialization that omit the number of elements. Selection guidance Conventions Sel Appropriate example Appropriate example of (1) extern char * mes[3]; char *mes[] = { "abc", "def", NULL}; Appropriate example of (2) extern char * mes[]; char *mes[] = { "abc", "def", NULL}; Appropriate example of (1) and (2) extern int var1[MAX]; int var1[MAX]; Inappropriate example Inappropriate example of (1) extern char * mes[]; char *mes[] = { "abc", "def", NULL}; Inappropriate example of (1) and (2) extern int var1[]; int var1[MAX]; Even if you make the extern declaration with the size of the array omitted, it will not cause an error. However, if the size is omitted it may cause problems for checking outside of the array range. For this reason, it is better to specify the array size at the time of declaration. However, there are cases when omitting the array size at declaration is better, such as

when the size of the array is determined by the number of initial values and thus the size is not uniquely fixed. [Related rules] R3.1.2

(p.47) R3.1.2 Iteration conditions for a loop that sequentially accesses elements in the array should include a determination if it is within the range of the array. Selection guidance Conventions Appropriate example char var1[MAX]; for (i = 0; i < MAX && var1[i] != 0; i++) { /*Even if 0 is not set in the var1 array there is no risk of accessing outside the array range*/ Inappropriate example char var1[MAX]; for (i = 0; var1[i] != 0; i++) { /* If 0 is not set in the var1 array, there is a risk of accessing outside the array range*/ This rule is to prevent accessing outside of the range. [Related rules] R3.1.1 Reliability 3.2: Divert error cases for operations that may cause errors at runtime. R3.2.1 Verify that the right-hand side of the expressions that calculate division or remainders is not 0 before executing the operation. Selection guidance Conventions Appropriate example if (y != 0) ans = x/y; Inappropriate example ans = x/y; Apart from when the value is obviously not 0, you should verify that the right-hand side of the expressions that calculate division or remainders is not 0 before executing the operation. Otherwise errors with 0 division may happen at runtime.

[Related rules] R3.2.2 R3.3.1

(p.48) R3.2.2 Check that the pointer is not a null pointer before referring to the location it points to. Selection guidance Conventions Appropriate example if (p != NULL) *p = 1; Inappropriate example *p = 1; [Related rules] R3.2.1 R3.3.1 Reliability 3.3: Check interface restrictions at function call. R3.3.1 If a function returns error information, then that error information shall be tested. [MISRA 16.10] Selection guidance Conventions Appropriate example p = malloc(BUFFERSIZE); if (p == NULL) /* Processing abnormal condition */ else *p = '0'; Inappropriate example p = malloc(BUFFERSIZE); *p = '0'; [Related rules] R3.2.1 R3.2.2 R3.5.1 R3.5.2

(p.49) R3.3.2 If there are restrictions to arguments passed to a function, you should verify that the used argument is not the restricted value before calling the function. Selection guidance Conventions Appropriate example if ((MIN <= para) && (para <= MAX)) ret = func(para); Inappropriate example ret = func(para); Reliability 3.4: Do not apply recursive calls. R3.4.1 Functions shall not call themselves, either directly or indirectly. [MISRA 16.2] Selection guidance Conventions Appropriate example Inappropriate example unsigned int calc(unsigned int n) { if ( n <= 1 ) { return 1; } return n * calc(n-1); } With recursive calls, the stack size used at runtime cannot be predicted, so there is a risk of stack overflow.

(p.50) Reliability 3.5: Pay attention to branching conditions and code should be described with how to respond when conditions that are not specified occur. R3.5.1 Put the else section the last in if-else if statements. If it is known that the else condition does not normally happen, apply one of the following: (i) Write how to process exceptions in the else section, (ii) Add a comment /* DO NOTHING */ in the else section. Selection guidance Conventions Appropriate example /* The else condition in a if-else if statement, with which the else condition does not normally happen */ if (var1 == 0) { } else if (0 < var1) { } else { /* State how to handle exceptions */ } if (var1 == 0) { } else if (0 < var1) { } else { /* DO NOTHING */ } Inappropriate example /* if-else if statement without the else section */ if (var1 == 0) { } else if (0 < var1) {

} If there is no else section in an if-else if statement, it is not clear if the programmer has forgotten the else section or if the else section will never happen. Even if it is known that the else condition does not normally happen, you can predict the behavior of the program under unexpected conditions by defining the else section in the following practice. - State the behavior of unexpected conditions in the else condition (determine how the program should behave in case the else condition occurs) In addition, the program is much easier to understand by just writing a comment that the else condition does not occur. - Add a comment specifying that the else condition does not occur, such as /*DO NOTHING */ to indicate that the else section is not missing. [Related rules] R3.3.1 R3.5.2

(p.51) Reliability 3.5.2 Put the default section the last in switch statements. If it is known that the default condition does not normally happen, apply one of the following: (i) State how to process exceptions in the default section, (ii) Add a comment /* DO NOTHING */ in the default section. Selection guidance Conventions Appropriate example /* The default condition in a switch statement, with which the default condition does not normally happen */ switch(var1) { case 0: break; case 1: break; default: /* State how to handle exceptions */ break; } switch(var1) { case 0: break; case 1: break; default: /* DO NOTHING */ break; }

Inappropriate example /* switch statement without the default section */ switch(var1) { case 0: break; case 1: break; } If there is no default section in a switch statement, it is not clear if the programmer has forgotten the default section or if the default section will never happen. Even if it is known that the default condition does not normally happen, you can predict the behavior of the program under unexpected conditions by defining the default section in the following practice. - State the behavior for unexpected conditions in the default condition (determine how the program should behave in case the default condition occurs) In addition, the program is much easier to understand by just writing a comment that the default condition does not occur. - Add a comment specifying that the default condition does not occur, such as /*DO NOTHING */ to indicate that the default section is not missing. (p.52) [Related rules] R3.3.1 R3.5.1 M3.1.4

R3.5.3 Do not use equality or inequality for loop counter comparison. (use "<=, >=, <, >") Selection guidance Conventions

Appropriate example void func() { int i; for (i = 0; i < 10; i++) { Inappropriate example void func() { int i; for (i = 0; i != 10; i++) { If the loop counter does not change by 1, it may result in an infinite loop. Do not use equality or inequality for comparisons that are concerned with loop repetition times.

(p.53) Reliability 3.6: Pay attention to the evaluation order. R3.6.1 Do not refer to or modify a variable in the same expression that states a change to that variable. Selection guidance Conventions Appropriate example f (x , x); x++; or f (x + 1, x); x++; Inappropriate example f (x , x++); The compiler does not guarantee the (evaluation) order of execution of each argument for functions with multiple arguments. The execution can start from the right or left of the arguments. Neither does the compiler guarantee the execution order of the left-hand or right-hand side of binary operations, such as plus operations. For this reason, if you update or refer to one object in a sequence of arguments or binary operation, the execution results are not guaranteed. Such problems, of which the execution results are not guaranteed, are called side-effect problems. You should not include codes that trigger side-effect problems. In this rule, statements like the example below, in which side-effect problems do not occur, are not prohibited. x = x + 1; x = f(x); [Related rules] R3.6.2 M1.8.1

(p.54) R3.6.2 More than one function call or volatile variables that have side effects should not be described in a sequence of arguments or binary operation. Selection guidance Conventions Appropriate example 1. extern int G_a; x = func1(); x += func2() ; int func1(void) { G_a += 10; } int func2(void) { G_a -= 10; } 2. volatile int v1, v2; y = v1; y += v2; 3. volatile int v; y = v; f(y, v); Inappropriate example 1. extern int G_a; x = func1() + func2( ) ; /* There is a side-effect problem */ int func1(void) { G_a += 10;

} int func2(void) { G_a -= 10; } 2. volatile int v1, v2; y = v1 + v2; 3. volatile int v; f(v, v); The compiler does not guarantee the (evaluation) order of execution of each argument for functions with multiple arguments. The execution can start from the right or left of the arguments. Neither does the compiler guarantee the execution order of the left-hand or right-hand side of binary operations, such as plus operations. For this reason, in a sequence of arguments or binary operation, if you include more than one function call or volatile variable that has side effects, the execution results may not be guaranteed. You should avoid such insecure coding. [Related rules] R3.6.1 M1.8.1

(p.55)

Maintainability
Many embedded software developments require maintenance tasks such as further working on the developed software. There are various reasons for maintenance, for example: If bugs that require modification are found in parts of the released software If new functions are added to existing software in response to market requests regarding the product. As described above, when the developed software is further worked on in one way or another, it is imperative to be able to perform that task as accurately and efficiently as possible. In the field of system development, it is called maintainability. In this section, practices to preserve and improve maintainability in relation to embedded software source code are categorized as follows. Maintainability 1: Be aware that other people are reading the program. Maintainability 2: Write in a way so as not to cause modification errors. Maintainability 3: Write programs in a simple way. Maintainability 4: Write in a unified way. Maintainability 5: Write in a way that is easy to test.

(p.56) Maintainability 1: Be aware that other people are reading the program. It is often the case that source code is reused and maintained by another engineer other than the original creator. For this reason, it is necessary to write source code using expressions easy to understand, considering the future possibility that other people will read it. Maintainability 1.1: Do not leave unused descriptions. Maintainability 1.2: Do not write in a way that may cause confusion. Maintainability 1.3: Do not write in a specialized way. Maintainability 1.4: Operations should be described in a way that their priority is clear. Maintainability 1.5: Do not omit operations that obtain function addresses or comparison operations. Maintainability 1.6: Use memory space for a sole purpose. Maintainability 1.7: Do not reuse names. Maintainability 1.8: Do not use language specifications that can cause misunderstanding. Maintainability 1.9: Clarify your intention when you use specialized writing. Maintainability 1.10: Do not embed magic numbers. Maintainability 1.11: Cleary state attributes of memory spaces. Maintainability 1.12: Statements that will not be compiled should also be described correctly.

(p.57) Maintainability 1.1: Do not leave unused descriptions. M1.1.1 Do not declare (define) unused functions, variables, arguments or labels. Selection guideline: Standardization Appropriate example void func(void) { Inappropriate example void func(int arg) { /* arg is not used */ Declaring (defining) unused functions, variables, arguments or labels impair maintainability as it is difficult to determine if the programmer has forgotten to delete them or has made an error. [Related rules] M1.9.1 M4.7.2 M1.1.2 Sections of code should not be commented out.[MISRA 2.4] Selection guideline: Standardization Appropriate example #if 0 /* Suppressed due to ~ */ a++; #endif Inappropriate example /* a++; */ If you need to suppress a part of the code, it is recommended to enclose that part in #if 0

rather than commenting it out. In this case you can also define rules how to clarify the suppressed part of code. However, under normal circumstances, leaving a suppressed part of code should be avoided as it makes the code difficult to read. [Related rules] M1.12.1 M4.7.2

(p.58) Maintainability 1.2: Do not write in a way that may cause confusion. M1.2.1 (1) Only one variable should be declared in one declaration statement (avoid multiple declaration). (2) Multiple automatic variables of the same type that are used for similar purposes can be declared in one declaration statement but variables to be initialized and variables not to be initialized should not be mixed. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) int i; int j; Appropriate example of (2) int i, j; int k = 0; int *p; int i; Inappropriate example Inappropriate example of (1) int i, j; Inappropriate example of (2) int i, j, k = 0; /* Variables to be initialized and variables not to be initialized are mixed (error) */ int *p, i; /* Variables of different types are mixed (error) */ If you declare a variable as int *p;, its type is int *, but if you declare variables as int *p, q;, the type for q is interpreted as int, not as int *. [Related rules] M1.6.1 M1.2.2 Constant descriptions that can use a suffix indicating appropriate types should be

described with a suffix. Use only an upper case L for a suffix indicating a long integer constant. Selection guideline: Standardization: Appropriate example void func(long int); fl oat f; long int l; unsigned int ui; f = f + 1.0F; /* Clearly state that it is a float operation */ func(1L); /* L should be upper case */ if (ui < 0x8000U) {/* Clearly state that it is an unsigned comparison */ Inappropriate example void func(long int); fl oat f; long int l; unsigned int ui; f = f + 1.0; func(1l); /* 1l can be confused with 11 */ if (ui < 0x8000) { (p.59) Essentially, if there is no suffix, integer constants will be int and floating constants will be double. However, when you describe a value of an integer constant that cannot be expressed with int, its type will be one that can express that value. For this reason, 0x8000 will be unsigned int if int is 16 bit, and signed int if int is 32 bit. If you would like to use it as unsigned you need to specify U as the suffix. In addition, in case of a target system that has a different operation speed for floating-point numbers that are float or double, you need

to be careful when applying an operation involving float variables and floating constants. This operation will be a double operation if you do not specify suffix F" for the floating constants. For floating constants, you need to make extra effort to specify that they are floating constants, for example by describing at least one number on both sides of the decimal point. [Related rules] M1.8.5 M1.2.3 When writing a lengthy string literal, use concatenation of successive string literals rather than starting new lines within the string literal. Selection guideline: Standardization: Appropriate example char abc[] = "aaaaaaaan" "bbbbbbbbn" "cccccccn"; Inappropriate example char abc[] = "aaaaaaaan bbbbbbbbn cccccccn"; If you want to write a lengthy string that can span multiple lines, it is easier to read if you concatenate multiple string literals.

(p.60) Maintainability 1.3: Do not write in a specialized way. M1.3.1 Expressions to examine true or false should not be described in switch (expression) expressions. Selection guideline: Standardization: Appropriate example if (i_var1 == 0) { i_var2 = 0; } else { i_var2 = 1; } Inappropriate example switch (i_var1 == 0) { case 0: i_var2 = 1; break; default: i_var2 = 0; break; } If you use an expression to examine true or false in the switch statement, the number of the branch will be two, and the necessity of having to use the switch statement, which is a multiple branching command, becomes low. Compared to if statements, switch statements have a higher possibility of error, such as writing the default section wrong or missing the break statement. Therefore, it is recommended to use if statements unless branches are three or more. M1.3.2 The case labels and the default label in switch statements should be described only in the compound statement (excluding its nested compound statements) of the switch statement body. Selection guideline: Standardization:

Appropriate example switch (x) { case 1: { } break; case 2: break; default: break; } Inappropriate example switch (x) { /* Compound statement of the switch statement body */ case 1: { /* Nested compound statements */ case 2: /* The case labels should not be described in nested compound statements */ } break; default: break; }

(p.61) M1.3.3 Types should be described clearly for definitions and declarations of functions and variables. Selection guideline: Standardization: Appropriate example extern int global; int func(void) { } Inappropriate example extern global; func(void) { } If you do not specify data types in definitions and declarations of functions and variables, they are interpreted as int but if you clearly specify data types, it is easier to read [Related rules] M4.5.1 Maintainability 1.4: Operations should be described in a way that their priority is clear. M1.4.1 Right-hand side and left-hand side of && and || operations should be described with simple variables or expressions in (). However, if successive && operations or successive || operations are combined, && and || expressions do not have to be in (). Selection guideline: Standardization: Appropriate example if ((x > 0) && (x < 10)) if ((!x) || y)

if ((fl ag_tb[i]) && status) if ((x != 1) && (x != 4) && (x != 10)) Inappropriate example if (x > 0 && x < 10) if (! x || y) if (fl ag_tb[i] && status) if (x != 1 && x != 4 && x != 10) Expressions that consist of simple variables and expressions in () are called primary expressions. Primary expressions also include constants and string literals. This rule defines that each term of && or || should be a primary expression. The aim is to improve readability by enclosing expressions that contain operators in (), making operations of each term in && or || operations prominent. [Related rules] R2.3.2 M1.5.2

(p.62) M1.4.2 <<Define how to use parentheses that specify priority of operations.>> Selection guideline: Standardization: Rul Appropriate example a = (b << 1) + c; or a = b << (1 + c); Inappropriate example a = b << 1 + c; /* There is a possibility that the priority is wrong */ Priority of operators for C language is easy to misunderstand so it is better to make rules as shown below. If an expression contains multiple binary operators with different priorities, you should use parentheses to clarify their priority. However, when using four mathematical operations, you can omit parentheses. [Related rules] M1.5.1 Maintainability 1.5: Do not omit operations that obtain function addresses or comparison operations. M1.5.1 A function identifier shall only be used with either a preceding &, or with a parenthesised parameter list, which may be empty. [Koenig 24] [MISRA 16.9] Selection guideline: Standardization:

Appropriate example

void func(void) ; void (*fp)(void) = &func; if (func()) { Inappropriate example void func(void) ; void (*fp)(void) = func; /* Error: There is no & */ if (func) { /* Error: It is obtaining the address rather than calling the function. It might be described as a function call without argument by mistake */ In C language, if a function name is described by itself it will not call the function but obtain the function address. This means that getting the function address does not require adding &. However, if you do not add &, there are cases when it is regarded as function call by mistake (for example, when you are using languages such as Ada, that describe only names when calling a sub-program that does not have an argument). By following the rule to add & when obtaining the function address, you can spot misunderstandings (errors) by detecting function names without & and not followed by (). [Related rules] M1.4.2

(p.63) M1.5.2 Comparisons with 0 should be explicit. Selection guideline: Standardization: Appropriate example int x = 5; if (x != 0) { } Inappropriate example int x = 5; if (x) { } Conditionals judge the expression result 0 as false and nonzero as true. For this reason, you can omit !=0 for expressions that judge conditions. However, it is better to not omit it to make the program clearer. [Related rules] R2.2.1 M1.4.1 Maintainability 1.6 Use a memory space for a sole purpose. M1.6.1 Provide variables according to each purpose. Selection guideline: Standardization: Appropriate example /* The counter variable and the variable for the interchanging task are different */ for (i = 0; i < MAX; i++) { data[i] = i; }

if (min > max) { wk = max; max = min; min = max; } Inappropriate example /* The counter variable and the variable for the interchanging task are the same */ for (i = 0; i < MAX; i++) { data[i] = i; } if (min > max) { i = max; max = min; min = i; } It is better not to reuse variables as it impairs readability and increases the risk of not being modified correctly at modification. [Related rules] M1.2.1

(p.64) M1.6.2 (1) Unions shall not be used. [Implementation 27] [MISRA 18.4] (2) When you use unions, use their members to access them. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (2) /* type is INTi_var, CHARc_var[4] */ struct stag { int type; union utag { char c_var[4]; int i_var; } u_var; } s_var; int i; if (s_var.type == INT) { s_var.u_var.i_var = 1; } i = s_var.u_var.i_var; Inappropriate example Inappropriate example of (2) /* type is INTi_var, CHARc_var[4] */ struct stag { int type; union utag { char c_var[4]; int i_var; } u_var; } s_var; int i;

if (s_var.type == INT) { s_var.u_var.c_var[0] = 0; s_var.u_var.c_var[1] = 0; s_var.u_var.c_var[2] = 0; s_var.u_var.c_var[3] = 1; } i = s_var.u_var.i_var; Unions allow you to declare one memory space using another memory space of a different size, but the way the bits between members overlap depends on implementation so it may result in unexpected behavior. If you use unions you need to pay attention to issues as in rule (2). [Related rules] R2.1.3

(p.65) Maintainability 1.7: Do not reuse names. M1.7.1 Name uniqueness should adhere to the following rules. 1. Identifiers in an inner scope shall not use the same name as an identifier in an outer scope, and therefore hide that identifier. [MISRA 5.2] 2. A typedef name shall be a unique identifier. [MISRA 5.3] 3. A tag name shall be a unique identifier. [MISRA 5.4] 4. No object or function identifier with static storage duration should be reused. [MISRA 5.5] 5. No identifier in one name space should have the same spelling as an identifier in another name space, with the exception of structure and union member names. [MISRA 5.6] Selection guideline: Standardization: Appropriate example int var1; void func(int arg1) { int var2; var2 = arg1; { int var3; var3 = var2; } } Inappropriate example int var1; void func(int arg1) { int var1; /* Using the same name as the variable outside the function */ var1 = arg1; { int var1;/* Using the same name as the variable in the outside scope */ var1 = 0; /* Which var1 is intended is unknown */ } }

You can make the program easier to read by keeping names unique within the program as much as possible, except for those with limited scope such as automatic variables. In C language, apart from file and block scopes, names have the following four namespaces according to categories they belong to: 1. labels 2. tags 3. members of structures and unions 4 other identifiers *macros do not have any namespace If the namespaces are different the language specification allows you to give the same name for multiple items, but this rule restricts it so as to make the program easier to read.

(p.66) [Related rules] M4.3.1 M1.7.2 Function names, variable names and macro names in the standard library should not be redefined or reused. Neither should their definitions be cancelled. Selection guideline: Standardization: Appropriate example #include <string.h> void *my_memcpy(void *arg1, const void *arg2, size_t size) { } Inappropriate example #undef NULL #defi ne NULL ((void *)0) #include <string.h> void *memcpy(void *arg1, const void *arg2, size_t size) { } Giving your own definition to function names, variable names and macro names defined in the standard library degrades readability of the program. [Related rules] M1.8.2 M1.7.3 Do not define names (variables) that start with an underscore. Selection guideline: Standardization:

Appropriate example __ Inappropriate example int _Max1; /* Reserved */ int __max2; /* Reserved */ int _max3; /* Reserved */ struct S { int _mem1; /* Not reserved but not to be used */ };

(p.67) C language standard defines the following names as reserved. (1) Names that start with an underscore followed by an uppercase alphabet character or names that start with an underscore followed by another underscore These names are always reserved for any kind of use. Example: _Abc, __abc (2) Names that start with one underscore These names are reserved for variables and functions with file scopes and for tags. If you redefine reserved names, behavior of the compiler is not guaranteed. Names that start with one underscore followed by a lower case alphabet character are not reserved for parts other than the file scope, but this rule restricts all names that start with an underscore to make it easy to remember. [Related rules] M1.8.2 Maintainability 1.8: Do not use language specifications that can cause misunderstanding. M1.8.1 The right-hand operand of a logical && or || operator shall not contain side effects. [MISRA 12.4] Selection guideline: Standardization: Appropriate example a = *p; p++; /* p has already been counted without being dependent on what p points to */ if ((MIN < a) && (a < MAX)) { } Inappropriate example /* Depending on whether what p point to is smaller than MIN or greater or equal to MIN, p is or is not counted (hard to understand) */ if ((MIN < *p) && (*p++ < MAX)) { }

The right-hand side of && or || operators may not be executed depending on the condition results of their left-hand side. If you use expressions that have side effects for the right hand side, such as increments, the condition of the left-hand side determines if it is incremented or not, causing some confusion. Therefore do not use expressions with side effects for the right-hand side of && or || operators. [Related rules] R3.6.1 R3.6.2

(p.68) M1.8.2 C macros shall only expand to a braced initialiser, a constant, a parenthesised expression, a type qualifier, a storage class specifier, or a do-while-zero construct. [Koenig 82-84] [MISRA 19.4] Selection guideline: Standardization: Appropriate example #defi ne START 0x0410 #defi ne STOP 0x0401 Inappropriate example #defi ne BIGIN { #defi ne END } #defi ne LOOP_STAT for(;;) { #defi ne LOOP_END } By using macro definitions freely, it is possible to make coding look as if it was written in another language other than C or to greatly reduce the amount of coding. However, using macros for these purposes will degrade readability. It is important to use macros only for where you can prevent coding and modification errors. As for do-while-zero, see MISRA-C: 2004. [Related rules] M1.7.2 M1.8.3 #line should not be used for another purpose other than automatic tool generation. Selection guideline: Standardization: #line is a function to modify file names or line numbers of warnings or error messages from the compiler. It is offered for code tool generation, and programmers should not use it directly.

(p.69) M1.8.4 Do not use a character sequence that starts with ?? and consists of three characters or more. Selection guideline: Standardization Appropriate example s = "abc?(x)"; Inappropriate example s = "abc??(x)"; /* Compilers that understand a trigraph sequence interpret this as abc[x) */ C language standard defines trigraph sequences that start with ?? to handle situations in which characters required for coding cannot be used in some development environment. The nine three-character patterns, ??=, ??(, ??/, ??), ??, ??<, ??!, ??> and ??- are replaced with one character #, [, \, ], ^, {, |, } and ~ respectively. This system is not frequently used, so many compilers support it optionally. M1.8.5 Octal constants (other than zero) and octal escape sequences shall not be used. [Koenig 9] [MISRA 7.1] Selection guideline: Standardization Appropriate example a = 0; b = 8; c = 100; Inappropriate example a = 000; b = 010; c = 100; Constants that start with 0 are interpreted as octal. You cannot add 0 in front of decimal numbers to align their digits. [Related rules] M1.2.2

(p.70) Maintainability 1.9: Clarify your intention when you use specialized writing. M1.9.1 If you need to intentionally describe statements that do nothing, use comments or blank macros to make a note of it. Selection guideline: Standardization Appropriate example for (;;) { /* Waiting for interruption */ } #defi ne NO_STATEMENT i = COUNT; while ((--i) > 0) { NO_STATEMENT; } Inappropriate example for (;;) { } i = COUNT; while ((--i) > 0); [Related rules] M1.2.2 M1.9.2 <<Regulate how to write infinite loops. >> Selection guideline: Standardization: Rul How to write infinite loops should be unified in the following ways, for example. - Infinite loops are unified with for(;;). - Infinite loops are unified with while(1). - Use infinite loops that are made into macros

(p.71) Maintainability 1.10: Do not embed magic numbers. M1.10.1 Define meaningful constants as macros before using them. Selection guideline: Standardization: Appropriate example #defi ne MAXCNT 8 if (cnt == MAXCNT) { Inappropriate example if (cnt == 8) { Constant meanings can be specified clearly by making them into macros. In this way, you can avoid modification errors when you modify a program in which constants are used in several places as you only need to modify one macro. However, sizeof, not macro, should be used for data sizes. [Related rules] M2.2.4 Maintainability 1.11: Cleary state attributes of memory spaces. M1.11.1 Memory spaces used only for reference should be declared with const. Selection guideline: Standardization: Appropriate example const volatile int read_only_mem; /* Memory only for reference */ const int constant_data = 10; be allocated */ /* Only refers to what arg points to */ void func(const char *arg, int n) { int i; for (i = 0; i < n; i++) { put(*arg++); /* Data only for reference that does not require memory to

} } Inappropriate example int read_only_mem; /* Memory only for reference */ int constant_data = 10; /* Data only for reference that does not require memory to be allocated */ /* Only refers to what arg points to */ void func(char *arg, int n) { int i; for (i = 0; i < n; i++) { put( *arg++ ); } } (p.72) Variables that are only for reference and are not modified can be made clear that they are not modified by declaring them with the const type. In addition, the compilers optimization process can make the object size smaller. For this reason, it is better if variables that are only for reference are const type. Memories that are modified by other execution units but only referred to by the program should be declared with a const volatile type so that the compiler can detect if the program will update them by mistake. You can also specify the function interface by adding const when memory spaces indicated by arguments are only for reference in function processing. [Related rules] R1.1.2 M1.11.2: Memory spaces that might be updated by other execution units should be declared with volatile. Selection guideline: Standardization: Appropriate example volatile int x = 1; while (x == 0) { /* x is not modified within the loop and modified by other execution unit*/ }

Inappropriate example int x = 1; while (x == 0) { /* x is not modified within the loop and modified by other execution unit*/ } Memory spaces qualified with volatile prohibit the compiler of optimization. Optimization prohibition means generating an execution object faithfully even to descriptions that are logically a pointless process. For example, suppose there is a description x;. Logically, it is a meaningless statement that only refers to the variable x, so if it is not qualified with volatile the compiler normally ignores such statements and does not generate an execution object. If it is qualified with volatile, it only refers to the variable x (loads it to the register). The meaning of this description is the interface IO register (maps to memories) that resets when memory is read. Embedded software is required to deal with the IO register to control hardware, so the volatile qualifier should be applied as required according to the IO register attributes.

(p.73) M1.11.3 <<Regulate variable declaration and definition rules for ROMification,>> Selection guideline: Standardization: Rul Appropriate example const int x = 100;/* Allocate it in the ROM */ Inappropriate example int x = 100; Variables that are qualified with const can be placed in memory spaces that are targets of ROMification. When you develop a program that performs ROMification, you should, for example, add a const qualifier to variables only for reference and specify section names to place using #pragma. [Related rules] R1.1.2 Maintainability 1.12: Statements that will not be compiled should also be described correctly. M1.12.1 Parts that are deleted by the preprocessor should also be described correctly. Selection guideline: Standardization: Appropriate example #if 0 /* */ # endif #if 0 #else int var; #endif #if 0

/* I don't know */ #endif Inappropriate example #if 0 /* # endif #if 0 #else1 int var; #endif #if 0 I don't know #endif [Related rules] M1.1.2

(p.74) Maintainability 2: Write in a way so as not to cause modification errors. One of the processes that introduce bugs into a program is when modifying a bug you embed another bug by mistake. Especially when it has been a while since the source code was written or when another engineer other than the creator is modifying the source code, it is quite possible that some unexpected misunderstandings occur. Efforts are required to reduce these modification errors as much as possible. Maintainability 2.1 Structured data and blocks should have clear grouping. Maintainability 2.2 Localize access range and related data.

(p.75) Maintainability 2.1 Structured data and blocks should have clear grouping. M2.1.1 If you initialize arrays and structures with values other than 0, you need to indicate the structure and use braces { } accordingly. Data should also be described without omissions, except when all values are 0. Selection guideline: Standardization: Appropriate example int arr1[2][3] = {{0, 1, 2}, {3, 4, 5}}; int arr2[3] = {1, 1, 0}; Inappropriate example int arr1[2][3] = {{0, 1, 2}, {3, 4, 5}}; int arr2[3] = {1, 1, 0}; Initialization for arrays and structures require at minimum a pair of braces but if there is only one pair of braces it is difficult to see how the initialized data is configured. It is safer to make initialized data into blocks according to the structure and to list values without omission. [Related rules] R1.2.1 M4.5.3 M2.1.2 Block the body of if, else if, else, while, do, for, switch statements. Selection guideline: Standardization: Appropriate example if (x == 1) { func(); } Inappropriate example if (x == 1) func();

If there are multiple statements (body) that are controlled by the if statement, they need to be in a block. If there is only one controlled statement, it does not need to be in a block but if some more statements are added during program modification, it is easy to forget to group them into a block. To prevent any modification errors, block the body of all control statements.

(p.76) Maintainability 2.2 Localize access range and related data. M2.2.1 Declare variables within the function if they are used only in that function. Selection guideline: Standardization: Appropriate example void func1(void) { static int x = 0; if (x != 0) {/* Refer to the last called value */ x++; } } void func2(void) { int y = 0; /* Initialize the value each time */ } Inappropriate example int x = 0; /* x is accessed only from func1 */ int y = 0; /* y is accessed only from func2 */ void func1(void) { if ( x != 0 ) { /* Refer to the last called value */ x++; } } void func2(void) { y = 0; /* Initialize the value each time */ } When you declare variables in functions, sometimes it is useful to add static. static adds the following characteristics:

- Static memory spaces are secured and the spaces are valid until the end of the program (without static, normally stack memory spaces are used and they are valid until the end of the function) - Initialization is once only after the program is started and if a function is called several times, values used in the previous call are retained Therefore, if you would like to retain values for variables that are only accessed within one function even after the function finishes, you should use static at declaration. In addition, if you declare large memory space for an automatic variable, it may cause a stack overflow. In such cases static can be added to secure static memory spaces even if the values do not need to be kept after the function finishes. However, for this usage, it is recommended that you specify your intentions using comments (as there is a risk of being misunderstood that the static was added by mistake). [Related rules] M2.2.2

(p.77) M2.2.2 Variables accessed by multiple functions defined within the same file should be declared with static in the file scope. Selection guideline: Standardization: Appropriate example /* x is not accessed by other files */ static int x; void func1(void) { x = 0; } void func2(void) { if (x == 0) { x++; } } Inappropriate example /* x is not accessed by other files */ int x; void func1(void) { x = 0; } void func2(void) { if (x==0) { x++; } }

The less global variables there are, the better readability is so as to understand the whole program. To prevent global variables from increasing, you should add a static storage-class specifier as much as possible to stop variables becoming global. [Related rules] M2.2.1 M2.2.3 M2.2.3 Functions that are called only by functions defined within the same file should be defined as static functions. Selection guideline: Standardization: Appropriate example /* func1 is not called by functions in other files */ static void func1(void) { } void func2(void) { func1(); } Inappropriate example /* func1 is not called by functions in other files */ void func1(void) { } void func2(void) { func1(); }

(p.78) The less global variables there are, the better readability is so as to understand the whole program. To prevent global variables from increasing, you should add a static storage-class specifier as much as possible to stop variables becoming global. [Related rules] M2.2.2 M2.2.4 Use enum rather than #define when defining related constants. Selection guideline: Standardization: Appropriate example enum euk { ENGLAND = 1, FRANCE = 2, }; Inappropriate example #defi ne ENGLAND 1 #defi ne FRANCE 2 [Related rules] M1.10.1 P1.3.2

(p.79) Maintainability 3: Write programs in a simple way. When it comes to software maintainability, nothing is better than software being written in a simple way. C language allows the structuring of software by methods such as dividing it into source files or dividing it into functions. Structured programming that represents program structure through sequence, selection and repetition, is also one of the techniques to write software in a simple way. Keep your mind set on writing software in a simple way by applying structured programming. You should also pay attention when using iteration processing, assignment or operations, since depending on how you write the code it can make the program difficult to maintain. Maintainability 3.1 Apply structured programming. Maintainability 3.2 There should be one side effect for one statement. Maintainability 3.3 Expressions with different purposes should be described separately. Maintainability 3.4 Avoid using complicated pointer operations.

(p.80) Maintainability 3.1 Apply structured programming. M3.1.1 For any iteration statement there shall be at most one break statement used for loop termination. [MISRA 14.6] Selection guideline: Standardization: Appropriate example end=0; for (i=0; loop iteration condition && !end; i++) { Iterated operation 1; if (end condition1 || end condition2) { end = 1; } else { Iterated operation 2; } } or for (i=0; loop iteration condition && !end; i++) { Iterated operation 1; if (end condition1 || end condition2) { break; } Iterated operation 2; } Inappropriate example for (i=0; loop iteration condition; i++) { Iterated operation 1; if (end condition1) { break; } if (end condition 2) { break; } Iterated operation 2; }

This rule is to prevent the program logic from becoming complex. If you need to have a flag solely to avoid use of the break statement, sometimes it is better not to have a flag and to use a break statement (beware that the example shown in the Appropriate example that uses an end flag can complicate the program).

(p.81) M3.1.2 (1) Do not use goto statements. (2) Use goto statements only when exiting multiple loops or when jumping to error handling. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) and (2) for (i = 0; loop iteration condition; i++) { Iterated operation; } Appropriate example of (2) if (err != 0) { goto ERR_RET; } ERR_RET: end_proc(); return err; } Inappropriate example Inappropriate example of (1) and (2) i = 0; LOOP: Iterated operation; i++; if (loop iteration condition) { goto LOOP; } This rule is to prevent the program logic from becoming complex. The aim is not to eliminate all goto statements; the idea is to remove unnecessary goto statements in order to avoid complicating the program (unable to read the program from top to bottom). There are occasions in which using goto statements can help improve readability. When writing a program, always consider the best way to express logic simply.

M3.1.3 The continue statement shall not be used. [MISRA 14.5] Selection guideline: Standardization:

Appropriate example for (i = 0; loop iteration condition 1; i++) { Iterated operation 1; if (! iteration condition 2) { Iterated operation 2; } } Inappropriate example for (i = 0; loop iteration condition 1; i++) { Iterated operation 1; if (iteration condition 2) { continue; } Iterated operation 2; } This rule is to prevent the program logic from becoming complex. The aim is not to eliminate all continue statements; the idea is to remove unnecessary continue statements in order to avoid complicating the program (unable to read the program from top to bottom). There are occasions in which using continue statements can help improve readability. When writing a program, always consider the best way to express logic simply.

(p.82) M3.1.4 (1) Always end the case and default sections in switch statements with the break statement. (2) If you do not end the case and default sections in switch statements with the break statement, <<regulate a comment in your project>> and insert that comment. Selection guideline: Standardization: Sel/Rul Appropriate example Appropriate example of (1) and (2) switch (week) { case A: code = MON; break; case B: code = TUE; break; case C: code = WED; break; default: code = ELSE; break; } Appropriate example of (2) dd = 0; switch (status) { case A: dd++; /* FALL THROUGH */ case B: Inappropriate example Inappropriate example of (1) and (2) /* No matter what value week has, code will be ELSE ==> bug */ switch (week) { case A:

code = MON; case B: code = TUE; case C: code = WED; default: code = ELSE; } /* This situation allows case B operation to continue but since there is no comment it is inappropriate not only for (1) but also for (2) */ dd = 0; switch (status) { case A: dd++; case B: Forgetting to put a break in switch statements in C language is one of the most common coding errors. Using case statements without a break unnecessarily should be avoided. If you would like the program to continue operation to the next case without the break statement, you should always add a comment to specify that lacking a break is not a problem. The coding convention should define what comments to be added. For example /* FALL THROUGH */ is a commonly used comment. [Related rules] R3.5.2

(p.83) M3.1.5 (1) Functions should end with one return statement. (2) return statements that return in the middle of an operation should be only for abnormal return. Selection guideline:

Standardization: Sel This rule is to prevent the program logic from becoming complex. If there are too many entry or exit points in the program, not only they complicate the program but they also make it hard to set break points during debugging. For C language, there is only one entry point for functions but the exit point is where you write return statements. Maintainability 3.2 There should be one side effect for one statement. M3.2.1 (1) Do not use comma expressions. (2) Do not use comma expressions other than in the initialization expressions or update expressions of for statements Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) and (2) a = 1; b = 1; j = 10; for (i = 0; i < 10; i++) { j--; } Appropriate example of (2) for (i = 0, j = 10; i < 10; i++, j--) { } Inappropriate example Inappropriate example of (1) and (2) a = 1, b = 1; Inappropriate example of (1) for (i = 0, j = 10; i < 10; i++, j--) { }

Comma expressions make the program complicated. However, initialization expressions and update expressions of the for statement are where operations that should be executed before and after the loop are described all together; sometimes it is easier to understand if you use comma expressions to describe them in a lot.

[Related rules] M3.3.1

(p.84) M3.2.2 Multiple assignments should not be described in one statement, except when you assign the same value to multiple variables. Selection guideline: Standardization: Appropriate example x = y = 0; Inappropriate example y = (x += 1) + 2; y = (a++) + (b++); Assignments include the compound assignments (+=, -= etc) as well as the simple assignment (=). It is possible to describe multiple assignments in one statement, but it degrades readability; assignments should be limited to only one per statement. However, the following well-used conventional descriptions do not always impair readability. You can define them as a rule to allow as an exception. c = *p++; *p++ = *q++; Maintainability 3.3 Expressions with different purposes should be described separately. M3.3.1 The three expressions of a for statement shall be concerned only with loop control. [MISRA 13.5] Selection guideline: Standardization: Appropriate example for (i =0; i < MAX; i++) { j++; } Inappropriate example for (i =0; i < MAX; i++, j++) { }

[Related rules] M3.2.1 M3.3.2

(p.85) M3.3.2 Numeric variables being used within a for loop for iteration counting shall not be modified in the body of the loop. [MISRA 13.6] Selection guideline: Standardization: Appropriate example for (i = 0; i < MAX; i++) { } Inappropriate example for (i = 0; i < MAX; ) { i++; } [Related rules] M3.3.1 M3.3.3 (1) Do not use assignment operators in expressions to examine true or false. (2) Do not use assignment operators in expressions to examine true or false, except for conventionally used expressions. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) and (2) p = top_p; if (p != NULL) { } Appropriate example of (1) c = *p++; while (c != '0') { c = *p++;

} Inappropriate example Inappropriate example of (1) and (2) if (p = top_p) { } Inappropriate example of (1) while (c = *p++) { } /* This is OK for (2) as it is a conventionally used expression (caution is required as it relies on the engineers skills) */ The following are expressions to obtain true or false: if (expression), for ( ;expression; ), while (expression), (expression)? :, expression && expression, expression || expression (p.86) Maintainability 3.4 Avoid using complicated pointer operations. M3.4.1 Do not use pointer specification that is in three or more stages. Selection guideline: Standardization: Appropriate example int **p; typedef char **strptr_t; strptr_t q; Inappropriate example int ***p; typedef char **strptr_t; strptr_t *q; It is difficult to understand pointer value transitions in three or more stages; it impairs maintainability.

(p.87) Maintainability 4: Write in a unified way. Recently, divided program developments involving several developers have become established. In such developments, if each developer writes source code in different styles, problems occur such as a difficulty in reviewing when checking each developers program content. In addition, if styles for naming variables and styles for content and ordering information in files are inconsistent, it can cause unexpected misunderstandings and errors. For this reason, it is said that in one project or organization it is better to unify how to write source code as much as possible. Maintainability 4.1 Unify coding styles. Maintainability 4.2 Unify how to write comments. Maintainability 4.3 Unify naming. Maintainability 4.4 Unify contents and their order in files. Maintainability 4.5 Unify how to write declarations. Maintainability 4.6 Unify how to write the null pointer. Maintainability 4.7 Unify how to write preprocessing directives.

(p.88) Maintainability 4.1 Unify coding styles. M4.1.1 <<Regulate conventions regarding the style, such as braces ({), indentation or adding spaces. >> Selection guideline: Standardization: Rul It is important to unify the coding style within the project to make codes easier to see. If your project is defining new style conventions, it is recommended that you select from coding styles that already exist. There are some schools for existing coding styles and most programmers write programs following any one of them. Another benefit from selecting from existing styles is that they can be specified easily by editors or editing command in the program. If an existing project does not clearly specify the coding style, it is recommended to apply the style that is closest to the current source code. Note that the most important issue when defining the style convention is to define with the purpose of unifying, not what style to define. The following are issues to be defined. (1) The location of braces ({}) The location of braces should be unified to clarify the beginning and end of a block (see Popular styles) (2) Indentation Indentation is to make a group of declarations and operations easier to see. What you need to define to unify indentation is as follows: Whether to use spaces or a tab for indentation. If spaces are used, how many space characters are included? If a tab is used how many spaces should a tab contain? (3) How to use space characters Space characters are used to make code easier to see and to make coding errors easier to spot. Define the following rules. Add a space before and after binary and ternary operators, except for the following operators. [], ->, . (period), , (comma operator) Do not add a space between unary operator and terms.

These rules facilitate discovering coding errors for compound assignment operators. (p.89) [Example] x=-1; /* An error that should be x-=1 => difficult to identify */ x =- 1; /* An error that should be x-=1 => easy to identify */ Apart from those stated above, the following rules can also be defined. Add a space after a comma (except for commas for arguments when defining macros) Add a space before the left parenthesis enclosing controlling expressions such as if or for. Do not add a space before the left parenthesis for function calls. These rules facilitate detecting function calls. (4) Location of new-lines in continuous lines When an expression becomes lengthy and goes beyond a point that is easy to see, you should start a new line at an appropriate location. When you make new-lines, it is recommended that you select one of the following two methods. What is important is to use an indentation when describing a continuous line. [Method1] Put an operator at the end of the line Example: x = var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9; if ( var1 == var2 && var3 == var4) [Method2] Put an operator at the beginning of the continuous line Example: x = var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9; if ( var1 == var2 && var3 == var4) Popular styles (1) K&R style A coding style used in The C Programming Language (known as K&R). Like the nickname of the book, it is taken from the initials of the two authors. The locations of braces and

indentation in the K&R style are as follows. Locations of braces Braces for function definitions should be at the beginning of a new line. Other braces (such as those in structures or control statements like if, for and while) should be on the same line without a new-line (see example). Indentation 1 tab. The first edition of The C Programming Language defined it as 5, but the second edition (supporting ANSI) defines it as 4.

(p.90) (2) BSD style A description style by Eric Allman, who wrote many BSD utilities. Also called the Allman style. The locations of braces and indentation in the BSD style are as follows. Locations of braces Indentation (3) GNU style A coding style used to write GNU packages. It is defined in GNU Coding Standards written by Richard Stallman and volunteers in the GNU project. The locations of braces and indentation in the GNU style are as follows. Locations of braces Function definition, if, for, while should all start in a new line. The braces for function definitions should be in column 0 and other braces should have an indentation of two spaces (see the example). Indentation 2. Braces and the body should both have two indents. Function definitions, if, for, while should all start in a new line and the brace should be placed in the column aligned with the previous line (see example). 8. There are also many cases of 4 spaces.

(1) K&R style example: void func(int arg1) { /* { in a function should start in a new line */ /* Indentation is one tab */ if (arg1) { } } (2) BSD style example: void func(int arg1) { /* { in a function should start in a new line */ if (arg1) { } /* something to do */ }

(3) GNU style example: void func(arg1) { /* { in a function should start in column 0 of a new line */ if (arg1) { } /* something to do */ }

(p.91) Maintainability 4.2 Unify how to write comments. M4.2.1 <<Define conventions regarding how to write file header comments, function header comments, end of line comments, block comments and copyright.>> Selection guideline: Standardization: Rul Program readability improves by writing comments well. To make it better, the method of writing needs to be unified. There are document generation tools that create documents for maintenance and investigation from the source code. When you utilize such tools you need to write in a way that follows their specifications. Generally, with document generation tools, when you write descriptions of variables and functions under certain comment conventions they are reflected from the source code to documents. You should check the specification of your tool and define comment conventions. The following introduces information on how to write comments from existing coding conventions and books. Typical way of writing comments (1) Indian Hill coding standards Indian Hill coding standards define the following comment rules. Block comment Used to describe data structure and algorithm. The format is to write / in the first column, all lines should have * in the second column and the end line should have */ in the second and the third columns (block comments can be extracted by grep ^.\*). Example /* Write a comment * Write a comment */ Location of comments - Block comments in functions Place them in appropriate locations, for example by aligning with the indent in the next line - End-of-line comments Place them far apart using tabs. If there are more than one of these comments align them with the same indentation.

(2) GNU coding standards GNU coding standards define the following comment rules. Language (p.92) Location and contents - At the beginning of the program All programs should start with comments that explain what they do. - Functions Each function should include the following comments. What the function does, explanation of arguments (value, meaning and purpose), return value - #endif Except for short conditions that are not nested, #endif should all have comments at the end of the line to clarify their conditions. - For tools Add two spaces at the end of comment sentences. (3) The Practice of Programming The Practice of Programming defines the following comment rules Location Other practices - Do not state the obvious. - Do not contradict codes. - Keep them clear and avoid comments that cause confusion. (4) Others Include the copyright notice in a form of a comment. Define comments for the case statement without a break. Example: switch ( status ) { case CASE1: Operation; /* FALL THROUGH */ case CASE2: Define comments for codes that do nothing. Write comments for functions and global data. English.

Example: if (Condition 1) { Operation; } else if (Condition 2) { Operation; } else { /* DO NOTHING */ } (p.93) Maintainability 4.3 Unify naming. M4.3.1<<Regulate conventions regarding naming external variables and internal variables.>> Selection guideline: Standardization: Rul See M4.3.2. [Related rules] M1.7.1 M1.7.2 M1.7.3 M4.3.2 <<Regulate conventions regarding naming files.>> Selection guideline: Standardization: Rul Readability of the program is greatly affected by naming. There are various methods for naming but what is important is uniformity and understandability. For naming, the following issues should be defined. Guidelines for names in general How to name files (including folders and directories) How to name globally and locally How to name macros etc

The following introduces some naming guidelines and rules from existing coding

conventions and books. Use them as a reference when you create new naming conventions in your project. If your existing project does not have clearly defined naming conventions, it is recommended to create conventions that are closest to the current source code. Typical naming conventions (1) Indian Hill coding standards Do not use names preceded or followed by an underscore; they are reserved for the system. Constant names that are defined with #define should all be in upper case. (p.94) Constants defined by enum should have the leading letter or all letters in upper case. Do not use two names with the difference being only their case (ex: foo and Foo). Global names should have a common prefix to indicate what module they belong to. File names should start with an alphabet followed by eight or less alphanumeric characters (excluding the extension). Avoid using the same name as header files in the library. Overall Do not use names preceded or followed by an underscore Do not use two names with the difference being only their case Variable and function names Others Global Local ex: foo and Foo Add a module name prefix. Nothing in particular Macro names should all be in upper case ex: #define MACRO enum members should have the leading letter or all letters in upper case (2) GNU coding standards Do not give names that are too short for global variables or functions. The names should be meaningful in English. Use underscores to divide words within a name. The upper case should be only used for macros, enum constants and prefixes for names following certain conventions. Normally names should only be in alphabet lower case.

Overall

Use underscores to divide words within a name ex: get_name Upper case should only be used for macros, enum constants and prefixes for names following certain conventions. Normally names should only be in alphabet lower case Do not give names that are too short. Should be meaningful in English Nothing in particular Macro names should all be in upper case ex: #define MACRO enum members should have all letters in upper case

Variable and function names Others

Global Local

(3) The Practice of Programming Give straightforward names globally and short names locally Give relevant names for those that are related so as to make their difference stand out. Function names should be based on active verbs followed by nouns if there are no particular problems. (p.95) Overall Variable and function names

Global Local Others

Give relevant names for related items Give names easy to understand Give short names Function names should be based on active verbs followed by nouns if there are not any particular problems

(4) Others How to delimit a name: If a name consists of multiple words, unify how to delimit them by selecting either using underscores or using an uppercase letter for the first letters of the words. Hungarian notation How to name files There is a notation such as Hungarian notation that clearly specify variable types. Give names with prefixes, for example indicating subsystems.

Maintainability 4.4 Unify contents and their order in files. M4.4.1 <<Regulate contents (ex. declarations and definitions) and their order to write in header files >> Selection guideline:

Standardization: Rul Items that are used commonly should be described in header files as they have a risk of modification errors if described in multiple places. Header files should contain a definition of macros commonly used in multiple source files, tag declarations for structures, unions and enumeration types, typedef declarations, external variable declarations and function prototype declarations. For example, they should be described in the following order: (1) File header comment (2) Including system headers (3) Including user-defined headers (4) #define macros (5) #define function macros (6) typedef definitions (type definitions for basic types such as int or char) (7) enum tag definitions (together with typedef definitions) (8) struct/union tag definitions (together with typedef definitions) (9) extern variable declarations (10) Function prototype declarations

(p.96) M4.4.2 <<Regulate contents (ex. declarations and definitions) and their order to write in source files >> Selection guideline: Standardization: Rul A common description order is including source files that contain commonly used declarations (#include), definitions and declarations of macros, tags, and types (typedef types) that are used only in individual C source files. For example, they should be described in the following order: (1) File header comment (2) Including system headers (3) Including user-defined headers (4) #define macros used only in your own files (5) #define function macros used only in your own files (6) typedef definitions used only in your own files (7) enum tag definitions used only in your own files (8) struct/union tag definitions used only in your own files (9) static variable declarations shared in the file (10) static function declarations (11) Function definitions * For (2) and (3), be careful to include only what is necessary. * Avoid describing (4) ~ (8) as much as possible.

(p.97) M4.4.3 When you use or define external variables or functions (except for functions used only within the file), include the header file that describes their declarations. Selection guideline: Standardization: Appropriate example --- my_inc.h --extern int x; int func(int); -------------#include "my_inc.h" int x; int func(int in) { Inappropriate example /* There is no declaration of the variable x or the function func */ int x; int func(int in) { In C language, variables should either be declared or defined before being used. On the other hand, functions can be used without declaration or definitions. However, to maintain the integrity of declarations and definitions, it is advisable to describe declarations in the header file and include that header file. M4.4.4 External variables should not be defined in multiple locations. Selection guideline: Standardization: Appropriate example int x; /* There should be only one declaration for one external variable */ Inappropriate example

int x; int x; /* Defining an external variable in multiple locations does not cause compile errors */ You can write multiple definitions without initialization for external variables. However, when an external variable is initialized in multiple files, the behavior is not guaranteed.

(p.98) M4.4.5 Do not write variable definitions or function definitions in the header file. Selection guideline: Standardization: Appropriate example --- fi le1.h --extern int x; /* Variable declaration */ int func(void) ; /* Function declaration */ --- fi le1.c --#include "fi le1.h" int x; { } Inappropriate example --- fi le1.h --int x; { } Header files might be included into multiple source files. For this reason, if you write variable or function definitions, the size of the object code generated after compilation may get unnecessarily too large. In general, header files should include only declarations or type definitions. M4.4.6 Header files should be created so that they are sustainable to redundant inclusions. <<Regulate how to write codes to achieve this.>> Selection guideline: Standardization: Rul Appropriate example /* External variable definition */ /* Function definition */ static int func(void) /* Variable definition */ int func(void) /* Function definition */

--- myheader.h --#ifndef MYHEADER_H #defi ne MYHEADER_H Header file content #endif /* MYHEADER_H */ Inappropriate example --- myheader.h --void func(void) ; /* end of fi le */ Header files should be organized as much as possible so that they will not have to be included redundantly. However, there are cases of redundant inclusions. To prepare for this, it is necessary to make them sustainable for redundant inclusions. For example, regulate the following rule. Example of a rule: Put a #ifndef macro that determines if the header has been included or not at the beginning of the header file so that in subsequent inclusions the following code is not compiled. The macro name for this should be the header file name with all letters transformed into the upper case and the dot changed into an _ (underscore).

(p.99) Maintainability 4.5 Unify how to write declarations. M4.5.1 (1) In the function prototype declaration, do not name any of the arguments (types only). (2) In the function prototype declaration, name all the arguments. In addition, argument types, name and return times should be literally the same as the function definition. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) int func1(int, int); int func1(int x, int y) { /* Processing functions */ } Appropriate example of (2) int func1(int x, int y); int func2(fl oat x, int y); int func1(int x, int y) { /* Processing functions */ } int func2(fl oat x, int y) { /* Processing functions */ } Inappropriate example Inappropriate example of (1) and (2) int func1(int x, int y); int func2(fl oat x, int y); int func1(int y, int x) /* Argument name is different from the prototype declaration */ {

/* Processing functions */ } typedef int INT; int func2(fl oat x, INT y) /* The type of y is not literally the same as the prototype declaration */ { /* Processing functions */ } In the function prototype declaration you can omit argument names, but appropriately describing argument names is valuable as function interface information. When you describe argument names, you should use the same name as the definition to avoid unnecessary confusion. As for types, it is easier to understand if they are literally the same as the function definition, so it is advisable to keep them the same. [Related rules] M1.4.1 (p.100) M4.5.2 Declare structure tags and variables separately. Selection guideline: Standardization: Appropriate example struct TAG{ int mem1; int mem2; }; struct TAG x; Inappropriate example struct TAG{ int mem1; int mem2; } x;

M4.5.3 (1) , should not be described in front of the last } in the list of initial value expressions for structures/unions/arrays, and the list of enumerators. (2) , should not be described in front of the last } in the list of initial value expressions for structures/unions/arrays, and the list of enumerators. However, writing , in front of the last } in the list of initial values for array initialization is an exception. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) struct tag data[] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } /* There is no comma after the last element */ }; Appropriate example of (2) struct tag data[] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, /* There is a comma after the last element */ }; Inappropriate example Inappropriate example of (1) and (2) struct tag x = { 1, 2, }; /* Whether there are two members or there are three or more members is unclear */ Initialization of multiple data has two styles: to omit adding a comma after the last initial value so as to specify the end of initialization, or to add a comma at the end in to make it easy to add or delete the initial value. Examine which to focus on to decide the rule. In C90 standard it was not acceptable to have ", just in front of } that indicates the end of an enumeration list, but it is acceptable in the C99 standard. [Related rules] M2.1.1

(p.101) Maintainability 4.6 Unify how to write the null pointer. M4.6.1 (1) Use 0 for the null pointer. Do not use NULL at all. (2) Use NULL for the null pointer. NULL should not be used for anything other than the null pointer. Selection guideline: Standardization: Sel Appropriate example Appropriate example of (1) char *p; int dat[10]; p = 0; dat[0] = 0; Appropriate example of (2) char *p; int dat[10]; p = NULL; int[0] = 0; Inappropriate example Inappropriate example of (1) char *p; int arr[10]; p = NULL; arr[0] = NULL; Inappropriate example of (2) char *p; int arr[10]; p = NULL; arr[0] = NULL;

NULL is an expression conventionally used for the null pointer, but expressions of the null pointer are different depending on operation environments. For this reason, some people consider that using 0 is safer.

(p.102) Maintainability 4.7 Unify how to write preprocessing directives. M4.7.1 Macros that contain operators should have the macro body and macro arguments enclosed in parentheses. Selection guideline: Standardization: Appropriate example #defi ne M_SAMPLE(a, b) ((a)+(b)) Inappropriate example #defi ne M_SAMPLE(a, b) a+b If you do not enclose macro bodies and arguments in parentheses, after expanding the macro, the operation order may not be what is expected, depending on the priority of operators next to the macro and operators within the macro, resulting in a bug,. M4.7.2 #else or #endif that correspond to #ifdef, #ifndef and #if should be described in the same file and their corresponding relationship should be expressed in comments. Selection guideline: Standardization: Appropriate example #ifdef AAA /* The operation when AAA is defined */ #else /* AAA */ /* The operation when AAA is not defined */ #endif /* AAA */ Inappropriate example #ifdef AAA /* The operation when AAA is defined */ #else /* The operation when AAA is not defined */

#endif If #else or #endif are described in distant locations or nested in an isolated process by macro such as #ifdef, their correspondence becomes difficult to understand. You should add comments to #else and #endif corresponding to #ifdef to make their correspondence easier to understand. [Related rules] M1.1.1 M1.1.2

(p.103) M4.7.3 When you check if a macro name has already been defined using #if, use defined (macro name). Do not write as #if macro name. Selection guideline: Standardization: Appropriate example #if defi ned(AAA) #endif Inappropriate example #if AAA #endif #if macro name cannot not determine if the macro has been defined or not. The result will be false not only when the macro is not defined but also when the macro is defined and the value is 0. To determine if a macro is defined or not, you should use defined. M4.7.4 Do not write a defined operator used in #if and #elif using styles other than defined (macro name) or defined macro name. Selection guideline: Standardization: Appropriate example #if defi ned(AAA) #endif Inappropriate example #defi ne DD(x) defi ned(x) #if DD(AAA) #endif In the C language standard, if you apply writing styles other than defined (macro name) or defined macro name, how they are processed is not defined (undefined). Avoid using a

writing style other than defined (macro name) or defined macro name, as the compiler may make it an error or interpret it in its own way.

(p.104) M4.7.5 Macros shall not be #defined or #undefd within a block. [MISRA 19.5] Selection guideline: Standardization: Appropriate example #defi ne AAA 0 #defi ne BBB 1 #defi ne CCC 2 struct stag { int mem1; char *mem2; }; Inappropriate example /* Members that have restrictions to the configured value exist */ struct stag { int mem1; /* Following values can be configured */ #defi ne AAA 0 #defi ne BBB 1 #defi ne CCC 2 char *mem2; }; In general, macro definitions (#define) should be described in bulk at the beginning of the file. If you disperse them, such as writing them within a block, readability will be degraded. In addition, undefining (#undef) them within a block will also degrade readability. Note that unlike variables, macro definitions have their scope up until the end of the file. It is possible that the Inappropriate example program can be changed in the following way: enum etag { AAA, BBB, CCC }; struct stag { enum etag mem1; char *mem2; };

[Related rules] M4.7.6 M4.7.6 #undef shall not be used. [MISRA 19.6] Selection guideline: Standardization: #defined macro names can be undefined with #undef, but interpretations may differ depending on where the macro name is referred to, degrading readability. [Related rules] M4.7.5

(p.105) Maintainability 5: Write in a way that is easy to test. One of the essential tasks in embedded software developments is checking operations (testing). However, problems can occur with recent complex embedded software, for example bugs and malfunctions detected during tests cannot be reproduced. For this reason, when you write source code, it is desirable to even consider how easy it is to analyze the cause of a problem. In addition, dynamic memories should be used with special care as they have risks such as memory leaks. Maintainability 5.1 Write in a way that is easy to examine the cause of problems. Maintainability 5.2 Pay attention to usages of dynamic memory allocations.

(p.106) Maintainability 5.1 Write in a way that is easy to examine the cause of problems. M5.1.1 <<Regulate the coding style for debugging when the debug option is set, and the coding style to write logs in the release module. >> Selection guideline: Standardization: Rul When you code programs, you should consider not only implementing certain functions but also facilitating investigation during debugging or when problems occur. Descriptions to facilitate problem investigation include the debug description, which is not reflected in the release module and the post release log output description, which is reflected also in the release module. The following explains how to determine conventions for each description. Debug description The debug description, such as the print statement used during program development should be described so that it is not reflected in the release modules. This section explains isolation using macro definition and utilizing assert macros. (a) Using macro definitions to isolate debugging description Utilize macro definitions that isolate if a part of the program is compiled or not so that the debugging description is not reflected in the release module. Strings such as DEBUG or MODULEA_DEBUG that include DEBUG are commonly used for the macro name. Examples of rule definitions: The debugging codes are isolated with #ifdef DEBUG (the DEBUG macro is specified at compilation). [Coding example] #ifdef DEBUG fprintf(stderr, "var1 = %dn", var1); #endif Moreover, you can use the following macro definitions. Examples of rule definitions: The debugging codes are isolated with #ifdef DEBUG (the DEBUG macro is specified at compilation). The following macro is used for outputting debugging information.

DEBUG_PRING (str) /* Output str to the standard output */ This macro is defined in the common header of the project, debug_macros.h, so include this header when you use the macro. -- debug_macros.h -#ifdef DEBUG #defi ne DEBUG_PRINT(str) fputs(str, stderr) #else #defi ne DEBUG_PRINT(str) ( (void) 0 ) /* no action */ #endif /* DEBUG */ [Coding example] void func(void) { DEBUG_PRINT(">> funcn"); DEBUG_PRINT("<< funcn"); } (b) Using assert macro The C language standard provides the assert macro as a program diagnosis function. The assert macro is useful as it facilitates detecting errors in the program during debugging. If you regulate and unify where to use the assert macro in the project, it makes debugging easier as you can gather consistent debugging information during the combined test. The rest of this section briefly explains how to use the assert macro. The following is a sample code for a function definition written under the premise that the pointer passed as an argument is never given a null pointer: void func( int *p ) { assert(p != NULL); *p = INIT_DATA; } If the NDEBUG macro is defined during compilation, the assert macro does not do anything. On the other hand, if the NDEBUG macro is not defined and the expression passed to the assert macro is false, it aborts after letting out the file name and the line

location of the source to the standard error. Note that the macro name is NDEBUG, not DEBUG. The asset macro is provided by the compiler in assert.h. Using the following as a reference, your project should examine how to abort and determine whether to use the macro provided by the compiler or to provide your own assert function. #ifdef NDEBUG #defi ne assert(exp) ( (void) 0 ) #else #defi ne 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 ); ffl ush ( stderr ); abort(); } Outputting logs after release It is useful to include descriptions for problem investigation also in the release module that does not contain debugging descriptions. The common method is to leave investigation information as a log. The log is helpful for validation tests for the release module and for investigation of problems that have occurred in the system offered to customers. If you leave log information, define the following issues and regulate them as a convention. Timing You should leave logs not only when an abnormal condition is found but also at times such as transmission with an external system to enable tracing the cause of the abnormal condition in the past history. Information to log You should record information that enables you to trace the cause of the abnormal condition in the past history, including the last performed process, data value or memory trace information. Macro or function to output information Localize log information output as a macro or a function as it is often useful if you can change the location for outputting logs. M5.1.2 (1) The # and ## preprocessor operators should not be used. [Unspecified 12] [MISRA 19.13]

(2) There shall be at most one occurrence of the # or ## preprocessor operators in a single macro definition. [Unspecified 12] [MISRA 19.12] Selection guideline: Standardization: Sel Appropriate example #defi ne AAA(a, b) a#b #defi ne BBB(x, y) x##y Inappropriate example #defi ne XXX(a, b, c) a#b##c The evaluation order of # and ## operators is not defined; do not mix # and ## operators and do not use them more than once.

(p.109) M5.1.3 Use functions rather than function-like macros. Selection guideline: Standardization: Appropriate example int func(int arg1, int arg2) { retrun arg1 + arg2; } Inappropriate example #defi ne func(arg1, arg2) (arg1 + arg2) Using functions rather than function-like macros facilitates tracking processes such as stopping in front of a function during debugging. In addition, it enables you to easily detect coding errors as the compiler executes type checking. [Related rules] E1.1.1 Maintainability 5.2 Pay attention to usages of dynamic memory allocations. M5.2.1 (1) Do not use dynamic memories. (2) If you use dynamic memories, <<regulate the upper limit of used memories, how to handle insufficient memories, and how to debug.>> Selection guideline: Standardization: Sel/Rul Using dynamic memory involves the risk of a memory leak that uses up the system resources by accessing invalid memory or by forgetting to return memory to the system. It is useful if you define rules to embed test codes to facilitate debugging in case of accidentally embedding these problems. Some compilers provide debugging functions as shown below. Check your compiler first. The open source also contains the source code for debugging, so you can use it as a reference when creating your own.

Rule definition example: Use X_MALLOC and X_FREE functions provided by the project, not the standard functions malloc or free, for obtaining and returning dynamic memories. Create debugging code by compiling it with -DDEBUG. (p.110) -- X_MALLOC.h -#ifdef DEBUG void *log_malloc( size_t size, char*, char* ); void log_free( void* ); #defi ne X_MALLOC(size) log_malloc( size, __FILE__, __LINE__ ) #defi ne X_FREE(p) log_free( p, __FILE__, __LINE__ ) #else #include <stdlib.h> #defi ne X_MALLOC(size) malloc( size ) #defi ne X_FREE(p) free( p ) #endif [Coding example] #include "X_MALLOC.h" p = X_MALLOC( sizeof(*p) * NUM ); if ( p == NULL ) { return ( MEM_NOTHING ); } X_FREE( p ); return ( OK ); Reference: Problems when using dynamic memories The following are problems that are likely to occur when using dynamic memories. Buffer overflow Making reference or updating beyond the range of obtained memory. Especially if you accidentally update outside the range, the problem does not occur in the location you updated but in the location in which the memory trashed by updating is referenced. The trouble with dynamic memories is that finding where memory is trashed is extremely difficult.

Omission of initialization Memory obtained using typical dynamic memory functions is not initialized (some functions that obtain dynamic memory apply initialization). As with the case of automatic variables, you need to initialize them in the program first before using them. Memory leaks They refer to memories that have been forgotten to be returned. It is not a problem with a program that ends each time. However, with a program that keeps operating, memory leaks will be the cause of memory depletion and system malfunction. Usage after return If you return memory using functions like free function, the memory may be reused by the malloc function that is called afterwards. For this reason, if you update using freed memory address you will be trashing memory used for other purposes. As was explained in the buffer overflow section, this problem is extremely difficult to debug. The code that creates these problems will not cause compilation errors. In addition, problems do not occur in the location where the bug is embedded, so they cannot be detected by tests that check typical specifications. You cannot debug them unless you execute tests by reviewing codes, inserting test codes to discover the above problems or embedding special libraries.

(p.111)

Portability
One of the characteristics of embedded software is that it has various options for platforms on which it operates. That is, there are many possible combinations of options for the MPU as the hardware platform and the OS as the software platform. As functions for implementation in embedded software increase, there are more and more opportunities to port existing software to another platform, by making one piece of software compatible on different platforms. Meanwhile, software portability is also becoming an extremely important element at the source code level. Coding that relies on the compiler is one of the most common errors. Portability 1: Write in a way that does not rely on the compiler.

Portability 2: Localize codes that have portability problems.

(p.112) Portability 1: Write in a way that does not rely on the compiler. Using the compiler (implementation) is unavoidable when using C language for programming. There are many existing implementations offered and each has its own individual characteristics. When creating the source code, if you apply inappropriate coding, you may end up relying on the characteristics of the implementation, causing unexpected situations when you use different implementations. For this reason, when you program, you should write in a way that does not rely on implementation. Portability 1.1: Do not use advanced functions or implementation-defined functions. Portability 1.2: Use only characters and escape sequences defined in the language standard. Portability 1.3: Verify and document the data type expressions, advanced functions for operations specifications and implementation-dependent sections. Portability 1.4: When including source files, check implementation-dependent sections and modify them to be independent. Portability 1.5: Write in a way that does not rely on the compilation environment.

(p.113) Portability 1.1: Do not use advanced functions or implementation-defined functions. P1.1.1 (1) Do not use functions that are not part of the C90 standards. (2) If you use a function that is not part of the C90 standards <<document the function you use and how to use it.>> Selection guidance: Convention: Sel/Doc The C90 standards do not support functions such as the // comment or the long long type, that are provided in recent compilers and included in the C99 standards. It is also realistic to select the rule (2) and allow the functions that are defined in the C99 standards. The following are rules regarding the details of how to use functions that are not part of the standards. This rule is an overview for the following. [Related rules] P1.1.3 P1.2.1 P1.2.2 P1.3.2 P2.1.1 P2.1.2 P1.1.2 All usage of implementation-defined behaviour shall be documented. [MISRA 3.1] Selection guidance: Convention: Doc In C90, there are 41 implementation-defined items other than the library section. For example, the following are implementation-defined and should be documented when you use them. How to express floating-point numbers How to handle signs for integer division remainders The search order of files for the #include directive #pragma Refer also to Appendix C Implementation definition documentation template.

(p.114) P1.1.3 If you are using a program written in other language, <<you should document its interface and define how to use it.>> Selection guidance: Convention: Doc/Rul The C language standards do not define the interface for utilizing a program that has been written in another language. That is, if you use a program written in another language, you are using an advanced function and this will affect portability. If you decide to use such a program you should regulate how to use it as well as documenting the compiler specification regardless of the possibility of porting.>> [Related rules] P1.1.1 P2.1.1 Portability 1.2: Use only characters and escape sequences defined in the language standard. P1.2.1 When writing a program, if you are using characters other than those defined in C90, you should check the compiler specifications <<and regulate how to use them.>> Selection guidance: Convention: Rul The minimum number of characters C90 defines are upper and lower cases of 26 alphabet letters, 10 decimal digits, 29 graphic characters, space characters, horizontal tabs, vertical tabs and control characters representing format feeding. In Japan, many compilers allow strings and comments in Japanese, but they can cause problems and should be used with care. For example, the second byte of the Shift-JIS character is \ in ASCII code; if you use it in the // comment it might be mistaken as a line concatenation. int index_arr[10]; //Index chart int *index_ptr = index_arr; //This line may be concatenated to the previous line. If you are using characters that are not defined in C90 (Japanese, for example), make sure that they can be used in the following locations and you should regulate how to use them:

Comments String literals - How to handle the situation if \ exists in the character codes of the string (whether special care is required or whether it should be specified as a compilation option etc) - If it is necessary to describe using the wide string literal (the prefix L such as L string). Character constants - The bit length of the character constant - If it is necessary to describe using the wide string literal (the prefix L such as L ). The file names to #include Define rules such as the following: - Writing comments in Japanese is allowed. The Japanese code used should be Shift_JIS. Do not use one-byte katakana. - Do not use Japanese for strings, string constants and file names to #include. [Related rules] P1.1.1 P1.2.2 Use only escape sequences defined in the language standard. Selection guidance: Convention: Appropriate example char c = 't'; /* OK */ Inappropriate example char c = 'x'; /* Error: this escape sequence is not defined in the language standard. Most implementations interpret it as x but there is no portability */ C90 defines the following seven escape sequences, including the new-line (\n). abfnrtv Behavior is not defined if undefined escape sequences are included in a character constant or a string literal (see C90 6.1.3.4).

[Related rules] P1.1.1

(p.116) Portability 1.3: Verify and document the data type expressions, advanced functions sections. P1.3.1: Char type as it is (signed or unsigned not specified) should be used for storing character values (processes) only; if implementation that depends on signed or unsigned (implementation-defined) is required use unsigned char or signed char. Selection guidance: Convention: Appropriate example char c = 'a'; /* Used to store characters */ int8_t i8 = -1 /* If you want to use it as 8bit data, use a type that is defined with typedef, for example. */ Inappropriate example char c = -1; if (c > 0) { } /* Inappropriate: Depending on implementation, char can be signed or unsigned and this difference affects the result of the comparison. */ Unlike other integer types such as int, if unspecified, char will be either signed or unsigned depending on the compiler used (int is the same as signed int). For this reason, using char without sign specification in situations that depend on signed or unsigned is not portable. This is because char without sign specification is an independent type provided for character storage (char, unsigned char and signed char are three different types) and the language specification assumes such a usage. If you need to use it as a small integer type, for example when you need an implementation that depends on signed or unsigned, you should specify signed or unsigned. In this case, it is desirable to typedef that type to localize the modification range for porting. . A similar problem to this rule is that the type returned by the standard function getc is int and cannot be received by char; this is a function interface problem (assignment that may cause information loss). [Related rules] P2.1.3 P1.3.2 Members of the enumeration type (enum) should be defined with values that can be for operations specifications and implementation-dependent

represented with int type. Selection guidance: Convention: Appropriate example /* If int 16bit, long 32bit */ enum largenum { LARGE = INT_MAX }; Inappropriate example /* If int 16bit, long 32bit */ enum largenum { LARGE = INT_MAX+1 }; With the C language specification, enumeration members should have values that are within the range to be represented by the int type. However, depending on the compiler, even if the functions are extended and the value exceeds the int type range, it may not cause an error. Reference: C++ allows values in long type range. [Related rule] P1.1.1 P1.3.3 (1) Do not use bit fields. (2) Do not use bit fields against data that takes bit positions into consideration. (3) If it is being relied upon, the implementation-defined behaviour and packing of bitfields shall be documented. [Unspecified 10; Implementation 30,31] [MISRA 3.5] Selection guidance: Convention: Sel/Doc Appropriate example Appropriate example of (2) struct S { unsigned int bit1:1; unsigned int bit2:1;

}; extern struct S * p; /* For example, p is acceptable if bit1 can be any bit in the data p points to, such as indicating just a group of flags */ p->bit1 = 1; Inappropriate example Inappropriate example of (2) struct S { unsigned int bit1:1; unsigned int bit2:1; }; extern struct S * p; /* For example, the program is not portable if the bit locations are significant, such as when p points to the IO port; in other words, it is important if bit1 points to the lowest or highest bit of data. */ p->bit1 = 1; /* To which bit it is set in the data that p points to depends on implementation */ The following bit field operations differ depending on which compiler is used. (1) Whether bit fields of the int type without sign specification is treated as signed (2) The order of the bit field assignment within the unit (3) The boundary of the bit field memory unit If you use bit fields to access data with bit locations that carry a meaning, such as accessing the IO port, it will cause a portability problem from the perspective of (2) and (3). For this reason, in such cases you should use bitwise operations such as & and |, not bit fields. [Related rules] R2.6.1

(p.118) Portability 1.4: When including source files, check implementation-dependent sections and modify them to be independent. P1.4.1 The #include directive shall be followed by either a <filename> or filename sequence. [Undefined 48] [MISRA 19.3] Selection guidance: Convention: Appropriate example #include <stdio.h> #include "myheader.h" #if VERSION == 1 #defi ne INCFILE "vers1.h" #elif VERSION == 2 #defi ne INCFILE "vers2.h" #endif #include INCFILE Inappropriate example #include stdio.h /* It has neither <> nor */ #include "myheader.h" 1 /* 1 is specified at the end */ In the C language standard, the behavior is not defined (undefined) for the situation when what follows after the #include directive is macro-extended does not match either the two styles (<....> or "...."). Most compilers cause an error if the format does not match either of the two, but there are situations when it does not cause an error, so use either format. P1.4.2 <<Define how to differentiate <> format and format in the file specification for #include.>> Selection guidance: Convention: Rul Appropriate example #include <stdio.h> #include "myheader.h"

Inappropriate example #include "stdio.h" #include <myheader.h> There are two ways to write #include. To unify the usage, regulate rules like the ones shown below. Enclose headers provided by the compiler in <> Enclose headers created by the project in Enclose headers provided by the purchased software xxx in (p.119) P1.4.3 Do not use characters , \, , /*, and : for #include file specifications. Selection guidance: Convention: Appropriate example #include "inc/my_header.h" /* OK */ Inappropriate example #include "incmy_header.h" /*Error */ If you use these characters (the following presents a more precise explanation), the behavior Is not defined in the C language standard. That is, how it operates is unknown thus it does not have portability. When characters ', \, or /* appear among the string enclosed in <> When characters ', \ or /* appear among the string enclosed in The operation of the character : (colon) differs depending on the implementation, so it does not have portability. Portability 1.5: Write in a way that does not rely on the compilation environment. P1.5.1 The absolute path should not be described for #include file specification. Selection guidance: Convention: Appropriate example #include "module1/h1.h"

Inappropriate example #include "/project1/module1/h1.h" If described using the absolute path, modification is required when the program is compiled after directories are changed.

(p.120) Portability 2: Localize codes that have portability problems. The principle is not to write implementation-dependent source code as much as possible, but sometimes such a description cannot be avoided. A typical example is when calling assembly language programs from C language. In such cases, it is advisable to localize these portions as much as possible. Portability 2.1: Localize codes that have portability problems.

(p.121) Portability 2.1: Localize codes that have portability problems. P2.1.1 When you are calling assembly language programs from C language, <<regulate how to localize them >> such as expressing them as C language functions that contain inline assembly language only or describe them using macros. Selection guidance: Convention: Rul Appropriate example #defi ne SET_PORT1 asm(" st.b 1, port1") void f() { SET_PORT1; } Inappropriate example void f() { asm(" st.b 1,port1"); } /* asm and other processes are mixed */ Many implementations provide extended support for the asm(string) format as a method to include the assembler. However, some implementations do not support it and even if the same format is used the behavior may be different so portability is unavailable. [Related rules] P1.1.1 P1.1.3 P2.1.2 For keywords extended by implementations, <<regulate macros>> and localize them. Selection guidance: Convention: Rul

Appropriate example /* interrupt is the keyword extended by a certain implementation. */ #defi ne INTERRUPT interrupt INTERRUPT void int_handler (void) { } Inappropriate example /* interrupt is the keyword extended by a certain implementation. It is used without being formed into a macro */ interrupt void int_handler(void) { }

(p.122) Some compilers do not use the #pragma directive but provide extended keywords; using such keywords does not have portability. When you use them it is important to localize them such as forming them into macros. As shown in the example, the macro is often named by changing the keyword name into the upper case. [Related rules] P1.1.1 P2.1.3 (1) The basic types such as char, int, long, float and double should not be used. Instead, types defined by typedef should be used. <<Regulate which types defined by typedef to be used in the project.>> (2) If the basic types such as char, int, long, float and double are used in a format that relies on their size, types created by defining each basic type with typedef should be used. <<Regulate typedef types used in the project.>> Selection guidance: Convention: Sel/Rul Appropriate example Appropriate example of (1) and (2) uint32_t fl ag32; /* Use unit32_t if 32 bit is assumed */

Appropriate example only for (2) int i: for (i = 0; i < 10; i++) { } /* i is used as an index. It can be 8bit, 16bit or 32bit and basic types in the language specification can be used */ Inappropriate example Inappropriate example of (1) and (2) unsigned int fl ag32; /* int is used by assuming it as 32bit */ The sizes and internal representations for each integer types including char, short, int and long are different depending on the compiler. C99 regulates the following typedef as the language standard. Refer to them as names to apply for typedef. int8_tint16_tint32_tint64_tuint8_tuint16_tuint32_tuint64_t [Related rules] P1.3.1

(p.123)

Efficiency
A peculiarity of embedded software is that it is embedded in a product to operate in the real world along with the hardware. There are various restrictions such as the MPU or memory also imposed on the software, to cut down the cost of the product. In addition, due to requirements such as the real-time aspect, it also needs to meet a strict time restriction. When you are coding embedded software, you should pay attention to resource efficiency such as memory or time efficiency that takes the time capability into consideration. Efficiency1: Write in a way that takes resource and time efficiencies into consideration.

(p.124) Efficiency1: Write in a way that takes resource and time efficiencies into consideration. Depending on how you write the source code, object sizes may increase or execution speeds may deteriorate. If you have restrictions on memory size and process time, extra effort is required to write codes that keep these issues in mind. Efficiency 1.1 Write in a way that takes resource and time efficiencies into consideration.

(p.125) Efficiency 1.1: Write in a way that takes resource and time efficiencies into consideration. E1.1.1 Macro functions should be used only in places related to speed capability. Selection guidance: Convention: Appropriate example #defi ne func(arg1,arg2) /* func is a complicated macro */ func(var1, var2); /* Speed capability is more important than the object size */ Inappropriate example #defi ne func(arg1,arg2) /* func is a complicated macro */ func(var1, var2); /* Speed capability is not important */ Functions are safer than macro functions and should be used as much as possible. However, functions may degrade speed capacity by processing calls and returns. For this reason, if you would like to improve the speed capacity, you should use macro functions. However, if you use too many macro functions, the code is replicated in each place the macro is used so the object size may increase (see the Related rules). [Related rules] M5.1.3 E1.1.2 Do not perform operations that do not change within an iterated process. Selection guidance: Convention: Appropriate example var1 = func(); for (i = 0; (i + var1) < MAX; i++) { } Inappropriate example /* Function func returns the same result */

for (i = 0; (i + func()) < MAX; i++) { } Repeating the same process that returns the same result is not efficient. In some cases you can rely on optimization of the compiler, but you need to be careful of cases in which the compiler does not recognize the repetition as shown in the example.

(p.126) E1.1.3 Use structure pointers as function arguments rather than structures. Selection guidance: Convention: Appropriate example typedef struct stag { int mem1; int mem2; } STAG; int func (const STAG *p) { return p->mem1 + p->mem2; } Inappropriate example typedef struct stag { int mem1; int mem2; } STAG; int func (STAG x) { return x.mem1 + x.mem2; } If you pass a structure as a function argument, when the function is called all the structure data is copied in the space for the argument; if the size of the structure is large it will degrade the speed capacity. If you are passing a structure only for reference, remember to qualify it with const as well as making it into a structure pointer. E1.1.4 <<Determine and regulate the selection policy regarding whether to use the switch statement or the if statement taking readability and efficiency into consideration. >> Selection guidance: Convention: Rul

The switch statement often has better readability than the if statement. In addition, recent compilers output optimized codes such as a table jump or binary search for the switch statement. Consider such factors when defining the rule. Example of a rule: When a process is branched according to the value of expressions (integer value), if the number of the branch is three or more, use the switch statement instead of the if statement. However, there are exceptions if the efficiency of the switch statement is an issue to improve the performance of the program.

(p.127)

Part 3 Typical embedded software coding errors


1 Meaningless expressions and statements 2. Wrong expressions and statements 3. Wrong memory usage 4. Errors caused by a misunderstanding of logical operations 5. Errors caused by typos 6. Descriptions that do not cause errors depending on the compiler

(p.128) Typical embedded software coding errors This section shows examples of coding errors that can be caused by even skilled programmers as well as C language beginners. Recent compilers optionally provide enhanced warning functions and some of what is explained here can be checked using the compilers warning or static analysis tools. However, by keeping these errors in mind at the coding stage you can reduce man-hours during the post-process task. Some existing coding conventions include these coding errors as rules. It is advisable to examine whether to include them into the convention by considering the skill levels of those involved in your development. This section discusses the following six points along with examples. Meaningless expressions and statements Wrong expressions and statements Wrong memory usage Errors caused by a misunderstanding of logical operations Errors caused by typos Descriptions that do not cause errors depending on the compiler 1 Meaningless expressions and statements If you leave statements or expressions that are not executed in the source code, it is likely to cause a misunderstanding, possibly resulting in a bug. It is particularly notable that confusion easily occurs when an engineer other than the one who created the source code adds a modification. Example 1: Writing unexecuted statements return ret; ret = ERROR; This problem is caused either by the programmer having made an error in the location of a statement (return, continue, break, goto statements) to branch the program control flow or having forgotten to delete an unnecessary statement when describing such a statement. Example 2: Writing unexecuted expressions size = sizeof(x++); The expression in the ( ) of the sizeof operation only calculates the size of the expression

type and does not execute the expression itself. Even if you describe the ++ operator as in the example, the value will not be incremented. Example 3: Writing statements that have unused execution results void func( ) { int cnt; cnt = 0; return; Automatic variables and parameters cannot be referenced after the function return. If an automatic variable or a parameter is updated but not referenced before the return statement, that update becomes an unnecessary expression (statement). Possibly some sort of operation has been missed or the unnecessary statement has been forgotten to be deleted during program modification. Example 4: Writing expressions that have unused execution results int func( ) { int cnt; return cnt++; The postfix ++ operation is updated after the value of the variable is referenced, so increments as in the example is meaningless. If you would like to return the incremented value to the caller, you should use the prefix increment. (p.130) Example 5: A value passed as an argument is not used. int func(int in) { in = 0; /* Overriding the argument */ } Overriding an argument without referencing it means that the value of the argument set by the caller is ignored. It may be a coding error.

2. Wrong expressions and statements When you create source code, it is necessary to follow the grammar defined in the programming language being used. No matter how knowledgeable you are about the programming language, it is possible to make inadvertent errors. The following are typical examples of wrong expressions and statements. Example 1: Specifying a wrong range if (0 < x < 10) The program above seems to be a correct description but C language does not interpret such a description in a mathematical way. It is a conditional expression which is always true. Example 2: Comparing outside the range unsigned char uc; unsigned int ui; if (uc == 256) switch (uc) { case 256: } if (ui < 0) The variable is compared with a value beyond the range it can express. uc can express only a value between 0 to 255 and is never a negative value. (p.131) Example 3: == operation cannot be used for string comparisons. if (str == "abc") The condition in the example compares addresses; it is not a condition to compare if the string abc is equal to the string specified by str. Example 4: Mismatch of the function type and the return statement

int func1(int in) { if (in < 0) return; /* Error */ return in ; } int func2(void) { /* Error */ return; } When you define a function that returns a value, you should describe the value to be returned in all the return statements (func1 function). In addition, the type of a function that has a return statement that does not return a value should be void (func2 function). 3. Wrong memory usage One characteristic of C language is that memory can be handled directly. This is a very useful advantage when creating embedded software, but caution is required when you use it as it often causes incorrect operations. Example 1: Referencing and updating outside the scope of the arrays char var1[N]; for (i = 1; i <= N; i++) { /* Accessing outside the scope of the array (error) */ var1[i] = i; } var1[-1] = 0; /* Error */ var1[N] = 0; /* Error */ The array index in C language starts with 0 and the maximum value is the number of elements minus 1. (p.132) Example 2: Errors caused by passing the address of an automatic variable to the return originator int *func(tag *p) { int x; p->mem = &x; /* The automatic variable memory space is referenced after the function return (risky) */

return &x; /* The automatic variable memory space is referenced after the function return (risky) */ } tag y; int *p; p = func(&y); *p = 10; /* Destroying invalid memory space */ *y.mem = 20; /* Destroying invalid memory space */ The memory spaces for automatic variables and parameters are released to the system when the function ends and may be used for other purposes. Like the example above, if you specify the address for the automatic variable memory space as a function return value or in the memory space referenced by the caller, it is possible to reference or update the memory spaces returned to the system and there is a risk of causing unexpected faults. Example 3: Referencing memories after the dynamic memory has been released struct stag { /* A list-structured structure */ struct stag *next; ... }; struct stag *wkp; /* A list structured pointer */ struct stag *top; /* The first pointer in the list structure */ ... /* Process to sequentially release list-structured structures */ /* After the release, the third controlling expression in the for statement accesses a released pointer; error */ for (wkp = top; wkp != NULL; wkp = wkp-> next) { free(wkp); } Memories obtained by using the malloc function need to be released to the system using the free function. The memory spaces released by the free function are reused by the system, so they should not be referenced. (p.133) Example 4: Error of writing string literals

char *s; s = "abc"; /* The memory space for the string literal may be ROM memory space */ s[0] = 'A'; /* Writing error */ Depending on the compiler, string literals are allocated to the const memory space. Programmers should be careful not to overwrite string literals. Example 5: Error when specifying copy sizes #defi ne A 10 #defi ne B 20 char a[A]; char b[B]; memcpy(a, b, sizeof(b)); When one array is copied to another, if you use the copy source size and it is bigger than the copy destination, it will destroy the memory space. When you copy arrays, the best way is to use arrays of the same size, but if you set the copy size to the size of the copy destination, at least you can avoid a memory crash. 4. Errors caused by a misunderstanding of logical operations It is comparatively easy to make errors when using logical operators. Caution is especially required for situations where these operators are used, as subsequent processes may differ depending on the operation results. Example 1: Accidentally using a logical multiplication instead of a logical addition if (x < 0 && x > 10) The above example is writing a logical multiplication when it should be a logical addition. Even when you write an impossible condition it does not cause an error in C language, so you should be careful. (p.134) Example 2: Accidentally using a logical addition instead of a logical multiplication int i, data[10], end = 0; for (i = 0; i < 10 || !end; i++) {

data[i] = Configured data; if (end condition) { end = 1; } }

/* it may crash outside the memory space */

When you add another condition for an iterated statement that sequentially references or updates array elements to a condition that prevents the array range from being exceeded, these conditions should be in logical multiplication. If you use a logical addition as in the example, there is a possibility of accessing outside of the array range. Example 3: Accidentally using a bit operator instead of a logical operator if (len1 & len2) This is an example of writing a bit AND operator (&) which is supposed to be a logical multiplication operator (&&). The bit AND operator does not apply logical multiplication to conditions. The meaning of the code should be described accurately.

5. Errors caused by typos Some C language operators, such as = and ==, change their meaning completely by trivial, inadvertent or careless mistakes. These operators should also be treated with due caution. Example 1: Accidentally using = operator instead of == operator if (x = 0) To compare if the values are equal, you should use ==, not =. Rules to prevent such coding errors include Do not use the assignment operator in expressions to examine true or false. Keep in mind that there are also cases of accidentally using == operator instead of = operator, such as a==b;. (p.135)

6. Descriptions that do not cause errors depending on the compiler Each compiler has various characteristics of its own. Caution is required as some compilers do not cause compile errors during compilation even if the program contains inappropriate descriptions. Example 1: Defining macros of the same name multiple times /* Depending on where AAA is referenced what is expanded is different */ #defi ne AAA 100 a = AAA;/* 100 is assigned */ #defi ne AAA 10 b = AAA;/* 10 is assigned */ Redefining a macro name defined with #define without applying #undef does not cause a compilation error with some compilers. If, depending on where it is used, a macro is expanded differently, it will degrade readability. Example 2: Error by writing into the const memory space void func(const int *p) { *p = 0; /* Writing into the const memory space (error) */ Some compilers do not cause a compilation error even if the const memory space is overwritten. Programmers should be careful not to overwrite the const memory space.

(p.137)

Appendix
Appendix A: List of practices and rules Appendix B: Rule categorization based on the C language grammar Appendix C: Implementation-defined functions template

(p.139) Appendix A: List of practices and rules [Reliability 1] R1 Initialize memory spaces and be mindful of their sizes. Practices Rule R1.1 The memory spaces R1.1.1 Automatic variables should be should be initialized before initialized at time of declaration or using them. assign initial values just before using them. R1.1.2 const variables should be initialized at time of declaration. R1.2 Initialization should be R1.2.1 When you initialize an array with a described in correct specified number of elements, you proportion. need to match the number of initial values with the number of elements specified. R1.2.2 Initialization of enumerated type (enum type) members should be one of the following: not specifying constants at all, specifying all constants, or specifying the first member only. R1.3 Pay attention to the range R1.3.1 (1) You should not make integer that the pointer points to. additions to or subtractions from (including ++ and --) pointers; use an array format with [] for references and assignments to the secured memory space. (2) Integer addition to or subtraction from (including ++ and --) pointers should be made only when the pointer points to the array and the result should point to within the range of the array. R1.3.2 Subtractions between pointers should 30 only be used for pointers that are pointing to elements in the same array. R1.3.3 Comparisons between pointers should 30 be applied only to pointers pointing to the elements of the same array or members of the same structure. [Reliability 2] R2 Pay attention to range, size and internal representation when using data. Practices Rule Page

Page 27

27 28

28

29

R2.1 Make comparisons that do not depend on internal representation.

R2.1.1 R2.1.2 R2.1.3

R2.2 Do not evaluate for equivalence to true values. R2.3 Operations and comparisons should be made to data with the same type.

R2.2.1 R2.3.1

R2.3.2

R2.3.3 R2.4 Code should be described while taking the operation precision into consideration. R2.4.1

R2.4.2

R2.5 Do not apply operations that have a risk of losing information.

R2.5.1

R2.5.2 R2.5.3

R2.5.4

Do not include equivalence or nonequivalence comparisons in floatingpoint expressions. Do not use a floating-point variable as a loop counter. Do not use memcmp to compare structures and unions. You should not make a comparison to a value defined as true in expressions that examine true and false. Unsigned integer constant expressions should be described within the range that can be represented with the result type. For a conditional operator (?: operator), logical expressions should be in parentheses and both return values should be the same type. Use the same type of variables for comparison of the loop counter and the loop iteration condition. When the operation type and the assignment designation type of the operation result are different, cast them to the type of operation precision expected first and then execute the operation. When you make arithmetic operations or comparisons that are mixed with signed and unsigned expressions, you should explicitly cast types into the expected type. When you assign (=operation, passing arguments in function calls, function return) or operate to data types that may cause information loss, you should check the existence of problems and describe casting to clearly indicate that there is no problem. Do not use the unary operator ('-') in unsigned expressions. When you apply bit complement (~) or left shift (<<) to data in unsigned char type or unsigned short type, you need to explicitly cast types to the type of the result. Right-hand side of the shift operator should be zero or more and less than the bit width of the left-hand side.

32 32 33 33 34

34

35 35

36

37

38 38

39

R2.6 Use types with which target data can be represented.

R2.6.1

R2.6.2 R2.7 Pay attention to the pointer type. R2.7.1

Limit types used for bit-fields only to signed int and unsigned int. If a bitfield of one bit width is required you should use unsigned int type, not signed. Data used as a bit sequence should be defined with unsigned type, not signed. (1) Pointer types should not be converted to other pointer types or integer types and vice versa. However, conversion between the void* type for the pointer type to data is an exception. (2) Pointer types should not be converted to other pointer types or int types less than the data width of the pointer type. However, conversion between the void* type for the pointer type to data is an exception. (3) Pointer types for data can be converted to pointer types of another data type, but pointers to function type should not be converted to pointer types for other function types or data types. When you convert a pointer type to the integer type, you should not convert to an integer type that is less than the data width of the pointer type. A cast shall not be performed that removes any const or volatile qualification from the type addressed by a pointer. [Undefined 39, 40] [MISRA 11.5] Do not examine if pointers are negative or not.

40

40 41

R2.7.2

42

R2.7.3

42

R2.8 Write in the way that the compiler can check if there is no contradiction in declarations, usages and definitions.

R2.8.1 R2.8.2

Functions without argument should be declared with the argument type as void. (1) Functions shall not be defined with a variable member of arguments. [Unspecified 15; Undefined 25, 45, 61, 70-76] [MISRA 16.1] (2) If you use functions with variable arguments <<you should document

43 43

behavior in implementation>>. R2.8.3 Prototype declarations should be made before function calls and function definitions. In addition, make sure that function calls and definitions refer to the same declaration. [Reliability 3] R3 Write in a way so as to secure the behavior. Practices Rule R3.1 Write code while keeping R3.1.1 (1) Ensure to specify the number of the size of the memory elements in the extern declaration space in mind. of the array. (2) Ensure to specify the number of elements in the extern declaration of the array, except for the extern declaration of arrays corresponding to an array definition with initialization that omit the number of R3.1.2 elements. Iteration conditions for a loop that sequentially accesses elements in the array should include a determination if it is within the range of the array. Verify that the right-hand side of the expressions that calculate division or remainders is not 0 before executing the operation. Check that the pointer is not a null pointer before referring to the location it points to. If a function returns error information, then that error information shall be tested. [MISRA 16.10] If there are restrictions to arguments passed to a function, you should verify that the used argument is not the restricted value before calling the function. Functions shall not call themselves, either directly or indirectly. [MISRA

44

Page 46

47

R3.2 Divert error cases for operations that may cause errors at runtime.

R3.2.1

47

R3.2.2 R3.3 Check interface restrictions at function call. R3.3.1 R3.3.2

48 48 49

R3.4 Do not apply recursive calls.

R3.4.1

49

R3.5 Pay attention to branching conditions and code should be described with how to respond when conditions that are not specified occur.

R3.5.1

16.2] Put the else section the last in if-else if statements. If it is known that the else condition does not normally happen, apply one of the following: (i) Write how to process exceptions in the else section, (ii) Add a comment /* DO NOTHING */ in the else section. Put the default section the last in switch statements. If it is known that the default condition does not normally happen, apply one of the following: (i) State how to process exceptions in the default section, (ii) Add a comment /* DO NOTHING */

50

R3.5.2

51

in the default section. R3.5.3 Do not use equality or inequality for loop counter comparison. (use "<=, >=, <, >") R3.6 Pay attention to the R3.6.1 Do not refer to or modify a variable in evaluation order. the same expression that states a change to that variable. R3.6.2 More than one function call or volatile variables that have side effects should not be described in a sequence of arguments or binary operation. [Maintainability 1] M1 Be aware that other people are reading the program. Practices Rule M1.1 Do not leave unused M1.1.1 Do not declare (define) unused descriptions. functions, variables, arguments or labels. M1.1.2 Sections of code should not be commented out.[MISRA 2.4]

52 53 54

Page 57 57

M1.2 Do not write in a way that may cause confusion.

M1.2.1

(1) Only one variable should be declared in one declaration statement (avoid multiple declaration). (2) Multiple automatic variables of the same type that are used for similar purposes can be declared in one declaration statement but variables to be initialized and variables not to be initialized should not be mixed. Constant descriptions that can use a suffix indicating appropriate types should be described with a suffix. Use only an upper case L for a suffix indicating a long integer constant. When writing a lengthy string literal, use concatenation of successive string literals rather than starting new lines within the string literal. Expressions to examine true or false should not be described in switch (expression) expressions. The case labels and the default label in switch statements should be described only in the compound statement (excluding its nested compound statements) of the switch statement body. Types should be described clearly for definitions and declarations of functions and variables. Right-hand side and left-hand side of && and || operations should be described with simple variables or expressions in (). However, if successive && operations or successive || operations are combined, && and || expressions do not have to be in (). <<Define how to use parentheses that specify priority of operations.>> A function identifier shall only be used with either a preceding &, or with a parenthesised parameter list, which may be empty. [Koenig 24] [MISRA 16.9] Comparisons with 0 should be explicit.

58

M1.2.2

58

M1.2.3

59

M1.3 Do not write in a specialized way.

M1.3.1 M1.3.2

60 60

M1.3.3 M1.4 Operations should be described in a way that their priority is clear. M1.4.1

61 61

M1.4.2 M1.5 Do not omit operations that obtain function addresses or comparison operations. M1.5.1

62 62

M1.5.2

63

M1.6 Use a memory space for a sole purpose.

M1.6.1 M1.6.2

Provide variables according to each purpose. (1) Unions shall not be used. [Implementation 27] [MISRA 18.4] (2) When you use unions, use their members to access them. Name uniqueness should adhere to the following rules. 1. Identifiers in an inner scope shall not use the same name as an identifier in an outer scope, and therefore hide that identifier. [MISRA 5.2] 2. A typedef name shall be a unique identifier. [MISRA 5.3] 3. A tag name shall be a unique identifier. [MISRA 5.4] 4. No object or function identifier with static storage duration should be reused. [MISRA 5.5] 5. No identifier in one name space should have the same spelling as an identifier in another name space, with the exception of structure and union member names. [MISRA 5.6] Function names, variable names and macro names in the standard library should not be redefined or reused. Neither should their definitions be cancelled. Do not define names (variables) that start with an underscore.

63 64

M1.7 Do not reuse names.

M1.7.1

65

M1.7.2

66

M1.7.3

66

M1.8 Do not use language specifications that can cause misunderstanding.

The right-hand operand of a logical && or || operator shall not contain side effects. [MISRA 12.4] M1.8.2 C macros shall only expand to a braced initialiser, a constant, a parenthesised expression, a type qualifier, a storage class specifier, or a do-while-zero construct. [Koenig 82-84] [MISRA 19.4] M1.8.3 #line should not be used for another purpose other than automatic tool generation. M1.8.4 Do not use a character sequence that starts with ?? and consists of three characters or more. M1.8.5 Octal constants (other than zero) and octal escape sequences shall not be used. [Koenig 9] [MISRA 7.1] M1.9 Clarify your intention M1.9.1 If you need to intentionally describe when you use specialized statements that do nothing, use writing. comments or blank macros to make a note of it. M1.9.2 <<Regulate how to write infinite loops. >> M1.10 Do not embed magic M1.10.1 Define meaningful constants as numbers. macros before using them. M1.11 Cleary state attributes of M1.11.1 Memory spaces used only for memory spaces. reference should be declared with const. M1.11.2 Memory spaces that might be updated by other execution units should be declared with volatile. M1.11.3 <<Regulate variable declaration and definition rules for ROMification,>> M1.12 Statements that will not M1.12.1 Parts that are deleted by the be compiled should also preprocessor should also be be described correctly. described correctly. [Maintainability 2] M2 Write in a way so as not to cause modification errors. Practices Rule M2.1 Structured data and M2.1.1 If you initialize arrays and structures blocks should have clear with values other than 0, you need to grouping. indicate the structure and use braces { } accordingly. Data should also be described without omissions, except when all values are 0. M2.1.2 Block the body of if, else if, else, while, do, for, switch statements.

M1.8.1

67 68

68 69 69 70

70 71 71 72 73 73

Page 75

75

M2.2 Localize access range and related data.

Declare variables within the function if they are used only in that function. M2.2.2 Variables accessed by multiple functions defined within the same file should be declared with static in the file scope. M2.2.3 Functions that are called only by functions defined within the same file should be defined as static functions. M2.2.4 Use enum rather than #define when defining related constants. [Maintainability 3] M3 Write programs in a simple way. Practices Rule M3.1 Apply structured M3.1.1 For any iteration statement there shall programming. be at most one break statement used for loop termination. [MISRA 14.6] M3.1.2 (1) Do not use goto statements. (2) Use goto statements only when exiting multiple loops or when M3.1.3 M3.1.4 jumping to error handling. The continue statement shall not be used. [MISRA 14.5] (1) Always end the case and default sections in switch statements with the break statement. (2) If you do not end the case and default sections in switch statements with the break statement, <<regulate a comment in your project>> and insert that M3.1.5 comment. (1) Functions should end with one return statement. (2) return statements that return in the middle of an operation should be M3.2 There should be one side effect for one statement. M3.2.1 only for abnormal return. (1) Do not use comma expressions. (2) Do not use comma expressions other than in the initialization expressions or update expressions M3.2.2 of for statements Multiple assignments should not be described in one statement, except when you assign the same value to multiple variables.

M2.2.1

76 77

77 78 Page 80 81

81 82

83

83

84

M3.3 Expressions with different purposes should be described separately.

M3.3.1 M3.3.2

M3.3.3

The three expressions of a for statement shall be concerned only with loop control. [MISRA 13.5] Numeric variables being used within a for loop for iteration counting shall not be modified in the body of the loop. [MISRA 13.6] (1) Do not use assignment operators in expressions to examine true or false. (2) Do not use assignment operators in expressions to examine true or false, except for conventionally

84 85

85

used expressions. M3.4 Avoid using complicated M3.4.1 Do not use pointer specification that is pointer operations. in three or more stages. [Maintainability 4] M4 Write in a unified way. Practices Rule M4.1 Unify coding styles. M4.1.1 <<Regulate conventions regarding the style, such as braces ({), indentation or adding spaces. >> M4.2 Unify how to write M4.2.1 <<Define conventions regarding how comments. to write file header comments, function header comments, end of line comments, block comments and copyright.>> M4.3 Unify naming. M4.3.1 <<Regulate conventions regarding naming external variables and internal variables.>> M4.3.2 <<Regulate conventions regarding naming files.>> M4.4 Unify contents and their M4.4.1 <<Regulate contents (ex. declarations order in files. and definitions) and their order to write in header files >> M4.4.2 <<Regulate contents (ex. declarations and definitions) and their order to write in source files >> M4.4.3 When you use or define external variables or functions (except for functions used only within the file), include the header file that describes their declarations. M4.4.4 External variables should not be defined in multiple locations. M4.4.5 Do not write variable definitions or function definitions in the header file. M4.4.6 Header files should be created so that they are sustainable to redundant inclusions. <<Regulate how to write codes to achieve this.>>

86 Page 88 91

93 93 95 96 97

97 98 98

M4.5 Unify how to write declarations.

M4.5.1

(1) In the function prototype declaration, do not name any of the arguments (types only). (2) In the function prototype declaration, name all the arguments. In addition, argument types, name and return times should be literally the same as the function definition. Declare structure tags and variables separately. (1) , should not be described in front of the last } in the list of initial value expressions for structures/unions/arrays, and the list of enumerators. (2) , should not be described in front of the last } in the list of initial value expressions for structures/unions/arrays, and the list of enumerators. However, writing , in front of the last } in the list of initial values for array initialization is an exception. (1) Use 0 for the null pointer. Do not use NULL at all. (2) Use NULL for the null pointer. NULL should not be used for anything other than the null pointer.

99

M4.5.2 M4.5.3

100 100

M4.6 Unify how to write the null pointer.

M4.6.1

101

M4.7 Unify how to write preprocessing directives.

Macros that contain operators should have the macro body and macro arguments enclosed in parentheses. M4.7.2 #else or #endif that correspond to #ifdef, #ifndef and #if should be described in the same file and their corresponding relationship should be expressed in comments. M4.7.3 When you check if a macro name has already been defined using #if, use defined (macro name). Do not write as #if macro name. M4.7.4 Do not write a defined operator used in #if and #elif using styles other than defined (macro name) or defined macro name. M4.7.5 Macros shall not be #defined or #undefd within a block. [MISRA 19.5] M4.7.6 #undef shall not be used. [MISRA 19.6] [Maintainability 5] M5 Write in a way that is easy to test. Practices Rule M5.1 Write in a way that is M5.1.1 <<Regulate the coding style for easy to examine the cause debugging when the debug option is of problems. set, and the coding style to write logs in the release module. >> M5.1.2 (1) The # and ## preprocessor operators should not be used. [Unspecified 12] [MISRA 19.13] (2) There shall be at most one occurrence of the # or ## preprocessor operators in a single macro definition. [Unspecified 12] M5.1.3 M5.2 Pay attention to usages of dynamic memory allocations. M5.2.1 [MISRA 19.12] Use functions rather than function-like macros. (1) Do not use dynamic memories. (2) If you use dynamic memories, <<regulate the upper limit of used memories, how to handle insufficient memories, and how to debug.>> [Portability 1] P1 Write in a way that does not rely on the compiler. Practices Rule

M4.7.1

102 102

103

103

104 104 Page 106

108

109 109

Page

P1.1 Do not use advanced functions or implementation-defined functions.

P1.1.1

(1) Do not use functions that are not part of the C90 standards. (2) If you use a function that is not part of the C90 standards <<document the function you use and how to use it.>> All usage of implementation-defined behaviour shall be documented. [MISRA 3.1] If you are using a program written in other language, <<you should document its interface and define how to use it.>> When writing a program, if you are using characters other than those defined in C90, you should check the compiler specifications <<and regulate how to use them.>> Use only escape sequences defined in the language standard. Char type as it is (signed or unsigned not specified) should be used for storing character values (processes) only; if implementation that depends on signed or unsigned (implementation-defined) is required use unsigned char or signed char. Members of the enumeration type (enum) should be defined with values that can be represented with int type. (1) Do not use bit fields. (2) Do not use bit fields against data that takes bit positions into consideration. (3) If it is being relied upon, the implementation-defined behaviour and packing of bitfields shall be documented. [Unspecified 10; Implementation 30,31] [MISRA 3.5]

113

P1.1.2 P1.1.3

113 114

P1.2 Use only characters and escape sequences defined in the language standard.

P1.2.1

114

P1.2.2 P1.3 Verify and document the data type expressions, advanced functions for operations specifications and implementationdependent sections. P1.3.1

115 116

P1.3.2 P1.3.3

116 117

P1.4 When including source files, check implementation-dependent sections and modify them to be independent.

The #include directive shall be followed by either a <filename> or filename sequence. [Undefined 48] [MISRA 19.3] P1.4.2 <<Define how to differentiate <> format and format in the file specification for #include.>> P1.4.3 Do not use characters , \, , /*, and : for #include file specifications. P1.5 Write in a way that does P1.5.1 The absolute path should not be not rely on the compilation described for #include file environment. specification. [Portability 2] P2 Localize codes that have portability problems. Practices Rule P2.1 Localize codes that have P2.1.1 When you are calling assembly portability problems. language programs from C language, <<regulate how to localize them >> such as expressing them as C language functions that contain inline assembly language only or describe them using macros. P2.1.2 For keywords extended by implementations, <<regulate macros>> and localize them. P2.1.3 (1) The basic types such as char, int, long, float and double should not be used. Instead, types defined by typedef should be used. <<Regulate which types defined by typedef to be used in the project.>> (2) If the basic types such as char, int, long, float and double are used in a format that relies on their size, types created by defining each basic type with typedef should be used. <<Regulate typedef types used in

P1.4.1

118

118 119 119

Page 121

121 122

the project.>> [Efficiency1] E1 Write in a way that takes resource and time efficiencies into consideration. Practices Rule Page

E1.1 Write in a way that takes resource and time efficiencies into consideration.

E1.1.1 E1.1.2 E1.1.3 E1.1.4

Macro functions should be used only in places related to speed capability. Do not perform operations that do not change within an iterated process. Use structure pointers as function arguments rather than structures. <<Determine and regulate the selection policy regarding whether to use the switch statement or the if statement taking readability and efficiency into consideration. >>

125 125 126 126

(p.151) Appendix B: Rule categorization based on the C language grammar This table categorizes the rules according to C language grammar Categorization by grammar No. Rule 1. Style 1.1 Syntax style M4.1.1 <<Regulate conventions regarding the style, such as braces ({), indentation or adding spaces. >> 1.2 Comments M4.2.1 <<Define conventions regarding how to write file header comments, function header comments, end of line comments, block comments and copyright.> 1.3 Naming M4.3.1 <<Regulate conventions regarding naming external variables and internal variables.>> M4.3.2 <<Regulate conventions regarding naming files.>> M1.7.1 Name uniqueness should adhere to the following rules. 1. Identifiers in an inner scope shall not use the same name as an identifier in an outer scope, and therefore hide that identifier. [MISRA 5.2] 2. A typedef name shall be a unique identifier. [MISRA 5.3] 3. A tag name shall be a unique identifier. [MISRA 5.4] 4. No object or function identifier with static storage duration should be reused. [MISRA 5.5] 5. No identifier in one name space should have the same spelling as an identifier in another name space, with the exception of structure and union member names. M1.7.2 [MISRA 5.6] Function names, variable names and macro names in the standard library should not be redefined or reused. Neither should their definitions be cancelled. Do not define names (variables) that start with an underscore.

M1.7.3

1.4 Structure within a file

M4.4.1 M4.4.5 M4.4.6

M4.4.2 M4.4.3

1.5 Constants

M1.2.2

M1.8.5 M1.2.3

M1.10.1 1.6 Others (style) M1.1.2 M1.9.1 M1.8.4 M5.1.3 2. Types

<<Regulate contents (ex. declarations and definitions) and their order to write in header files >> Do not write variable definitions or function definitions in the header file. Header files should be created so that they are sustainable to redundant inclusions. <<Regulate how to write codes to achieve this.>> <<Regulate contents (ex. declarations and definitions) and their order to write in source files >> When you use or define external variables or functions (except for functions used only within the file), include the header file that describes their declarations. Constant descriptions that can use a suffix indicating appropriate types should be described with a suffix. Use only an upper case L for a suffix indicating a long integer constant. Octal constants (other than zero) and octal escape sequences shall not be used. [Koenig 9] [MISRA 7.1] When writing a lengthy string literal, use concatenation of successive string literals rather than starting new lines within the string literal. Define meaningful constants as macros before using them. Sections of code should not be commented out.[MISRA 2.4] If you need to intentionally describe statements that do nothing, use comments or blank macros to make a note of it. Do not use a character sequence that starts with ?? and consists of three characters or more. Use functions rather than function-like macros.

2.1 Basic types

P2.1.3

(1) The basic types such as char, int, long, float and double should not be used. Instead, types defined by typedef should be used. <<Regulate which types defined by typedef to be used in the project.>> (2) If the basic types such as char, int, long, float and double are used in a format that relies on their size, types created by defining each basic type with typedef should be used. <<Regulate typedef types used in the project.>> Char type as it is (signed or unsigned not specified) should be used for storing character values (processes) only; if implementation that depends on signed or unsigned (implementation-defined) is required use unsigned char or signed char. Data used as a bit sequence should be defined with unsigned type, not signed. Declare structure tags and variables separately. (1) Unions shall not be used. [Implementation 27] [MISRA 18.4] (2) When you use unions, use their members to access them. Do not use memcmp to compare structures and unions. (1) Do not use bit fields. (2) Do not use bit fields against data that takes bit positions into consideration. (3) If it is being relied upon, the implementation-defined behaviour and packing of bitfields shall be documented. [Unspecified 10; Implementation 30,31] [MISRA 3.5] Limit types used for bit-fields only to signed int and unsigned int. If a bit-field of one bit width is required you should use unsigned int type, not signed.

P1.3.1

R2.6.2 2.2 Structures and Unions M4.5.2 M1.6.2

R2.1.3 2.3 Bitfields P1.3.3

R2.6.1

2.4 Enumeration type

R1.2.2

M2.2.4 P1.3.2 3. Declarations and definitions 3.1 Initialization R1.1.1 R1.1.2 R1.2.1

Initialization of enumerated type (enum type) members should be one of the following: not specifying constants at all, specifying all constants, or specifying the first member only. Use enum rather than #define when defining related constants. Members of the enumeration type (enum) should be defined with values that can be represented with int type. Automatic variables should be initialized at time of declaration or assign initial values just before using them. const variables should be initialized at time of declaration. When you initialize an array with a specified number of elements, you need to match the number of initial values with the number of elements specified. Do not include equivalence or nonequivalence comparisons in floating-point expressions. (1) , should not be described in front of the last } in the list of initial value expressions for structures/unions/arrays, and the list of enumerators. (2) , should not be described in front of the last } in the list of initial value expressions for structures/unions/arrays, and the list of enumerators. However, writing , in front of the last } in the list of initial values for array initialization is an exception.

M2.1.1 M4.5.3

3.2 Variable declarations and definitions

M1.2.1

(1) Only one variable should be declared in one declaration statement (avoid multiple declaration). (2) Multiple automatic variables of the same type that are used for similar purposes can be declared in one declaration statement but variables to be initialized and variables not to be initialized should not be mixed. Memory spaces used only for reference should be declared with const. Memory spaces that might be updated by other execution units should be declared with volatile. Declare variables within the function if they are used only in that function. Variables accessed by multiple functions defined within the same file should be declared with static in the file scope. External variables should not be defined in multiple locations. Provide variables according to each purpose. <<Regulate variable declaration and definition rules for ROMification,>>

M1.11.1 M1.11.2 M2.2.1 M2.2.2 M4.4.4 M1.6.1 M1.11.3

3.3 Function declarations and definitions

R2.8.3

M4.5.1

Prototype declarations should be made before function calls and function definitions. In addition, make sure that function calls and definitions refer to the same declaration. (1) In the function prototype declaration, do not name any of the arguments (types only). (2) In the function prototype declaration, name all the arguments. In addition, argument types, name and return times should be literally the same as the function definition. Functions without argument should be declared with the argument type as void. (1) Functions shall not be defined with a variable member of arguments. [Unspecified 15; Undefined 25, 45, 61, 70-76] [MISRA 16.1] (2) If you use functions with variable arguments <<you should document behavior in implementation>>. Functions that are called only by functions defined within the same file should be defined as static functions. (1) Ensure to specify the number of elements in the extern declaration of the array. (2) Ensure to specify the number of elements in the extern declaration of the array, except for the extern declaration of arrays corresponding to an array definition with initialization that omit the number of elements. Do not declare (define) unused functions, variables, arguments or labels. Expressions to examine true or false should not be described in switch (expression) expressions.

R2.8.1 R2.8.2

M2.2.3 3.4 Array declarations and definitions R3.1.1

3.5 Others (declarations and definitions)

M1.1.1 M1.3.1

4. Expressions

4.1 Function call

R3.3.2

R3.3.1 R3.4.1

If there are restrictions to arguments passed to a function, you should verify that the used argument is not the restricted value before calling the function. If a function returns error information, then that error information shall be tested. [MISRA 16.10] Functions shall not call themselves, either directly or indirectly. [MISRA 16.2]

4.2 Pointer

R2.7.1

(1) Pointer types should not be converted to other pointer types or integer types and vice versa. However, conversion between the void* type for the pointer type to data is an exception. (2) Pointer types should not be converted to other pointer types or int types less than the data width of the pointer type. However, conversion between the void* type for the pointer type to data is an exception. (3) Pointer types for data can be converted to pointer types of another data type, but pointers to function type should not be converted to pointer types for other function types or data types. When you convert a pointer type to the integer type, you should not convert to an integer type that is less than the data width of the pointer type. (1) You should not make integer additions to or subtractions from (including ++ and --) pointers; use an array format with [] for references and assignments to the secured memory space. (2) Integer addition to or subtraction from (including ++ and --) pointers should be made only when the pointer points to the array and the result should point to within the range of the array. Subtractions between pointers should only be used for pointers that are pointing to elements in the same array. Comparisons between pointers should be applied only to pointers pointing to the elements of the same array or members of the same structure. Do not examine if pointers are negative or not. Check that the pointer is not a null pointer before referring to the location it points to. Do not use pointer specification that is in three or more stages. (1) Use 0 for the null pointer. Do not use

R1.3.1

R1.3.2 R1.3.3

R2.7.3 R3.2.2 M3.4.1 M4.6.1

4.3 Cast

R2.4.2

R2.7.2

4.4 Unary operation

R2.5.1

M1.5.1

4.5 Addition, subtraction, multiplication and division 4.6 Shift

R3.2.1

R2.5.3

4.7 Comparison

R2.1.1 R2.2.1 M1.5.2 R2.5.2 M1.4.1

4.8 Bit operation 4.9 Logical operation

M1.8.1 4.10 Ternary operation R2.3.2

When you make arithmetic operations or comparisons that are mixed with signed and unsigned expressions, you should explicitly cast types into the expected type. A cast shall not be performed that removes any const or volatile qualification from the type addressed by a pointer. [Undefined 39, 40] [MISRA 11.5] When you assign (=operation, passing arguments in function calls, function return) or operate to data types that may cause information loss, you should check the existence of problems and describe casting to clearly indicate that there is no problem. A function identifier shall only be used with either a preceding &, or with a parenthesised parameter list, which may be empty. [Koenig 24] [MISRA 16.9] Verify that the right-hand side of the expressions that calculate division or remainders is not 0 before executing the operation. When you apply bit complement (~) or left shift (<<) to data in unsigned char type or unsigned short type, you need to explicitly cast types to the type of the result. Do not include equivalence or nonequivalence comparisons in floating-point expressions. You should not make a comparison to a value defined as true in expressions that examine true and false. Comparisons with 0 should be explicit. Do not use the unary operator ('-') in unsigned expressions. Right-hand side and left-hand side of && and || operations should be described with simple variables or expressions in (). However, if successive && operations or successive || operations are combined, && and || expressions do not have to be in (). The right-hand operand of a logical && or || operator shall not contain side effects. [MISRA 12.4] For a conditional operator (?: operator), logical expressions should be in parentheses and both return values should be the same type.

4.11 Assignment

R2.5.1

R2.4.1

M3.3.3

When you assign (=operation, passing arguments in function calls, function return) or operate to data types that may cause information loss, you should check the existence of problems and describe casting to clearly indicate that there is no problem. When the operation type and the assignment designation type of the operation result are different, cast them to the type of operation precision expected first and then execute the operation. (1) Do not use assignment operators in expressions to examine true or false. (2) Do not use assignment operators in expressions to examine true or false, except for conventionally used expressions. (1) Do not use comma expressions. (2) Do not use comma expressions other than in the initialization expressions or update expressions of for statements Do not refer to or modify a variable in the same expression that states a change to that variable. More than one function call or volatile variables that have side effects should not be described in a sequence of arguments or binary operation. <<Define how to use parentheses that specify priority of operations.>> Unsigned integer constant expressions should be described within the range that can be represented with the result type. Put the else section the last in if-else if statements. If it is known that the else condition does not normally happen, apply one of the following: (i) Write how to process exceptions in the else section, (ii) Add a comment /* DO NOTHING */ in the else section.

4.12 Comma

M3.2.1

4.13 Priorities and sideeffects

R3.6.1 R3.6.2

M1.4.2 4.14 Others (expressions) 5. Statements 5.1 if statement R2.3.1

R3.5.1

5.2 switch statement

M3.1.4

(1) Always end the case and default sections in switch statements with the break statement. (2) If you do not end the case and default sections in switch statements with the break statement, <<regulate a comment in your project>> and insert that comment. Put the default section the last in switch statements. If it is known that the default condition does not normally happen, apply one of the following: (i) State how to process exceptions in the default section, (ii) Add a comment /* DO NOTHING */ in the default section. Expressions to examine true or false should not be described in switch (expression) expressions. The case labels and the default label in switch statements should be described only in the compound statement (excluding its nested compound statements) of the switch statement body.

R3.5.2

M1.3.1 M1.3.2

5.3 for/while statement

R2.1.2 R2.3.3 R3.5.3 M3.3.1 M3.3.2

M3.1.1 M3.1.3 R3.1.2

Do not use a floating-point variable as a loop counter. Use the same type of variables for comparison of the loop counter and the loop iteration condition. Do not use equality or inequality for loop counter comparison. (use "<=, >=, <, >") The three expressions of a for statement shall be concerned only with loop control. [MISRA 13.5] Numeric variables being used within a for loop for iteration counting shall not be modified in the body of the loop. [MISRA 13.6] For any iteration statement there shall be at most one break statement used for loop termination. [MISRA 14.6] The continue statement shall not be used. [MISRA 14.5] (1) Do not use goto statements. (2) Use goto statements only when exiting multiple loops or when jumping to error handling. <<Regulate how to write infinite loops. >> Block the body of if, else if, else, while, do, for, switch statements. (1) Do not use goto statements. (2) Use goto statements only when exiting multiple loops or when jumping to error handling. (1) Functions should end with one return statement. (2) return statements that return in the middle of an operation should be only for abnormal return. Multiple assignments should not be described in one statement, except when you assign the same value to multiple variables.

5.4 Others (statements)

M1.9.2 M2.1.2 M3.1.2

M3.1.5

M3.2.2 6. Macros and preprocessors

6.1 #if related

M4.7.2

M4.7.3

M4.7.4 6.2 #include P1.4.1 P1.4.2 P1.4.3 P1.5.1 6.3 Macros M4.7.1 M1.8.2

M4.7.5 6.4 Others (macros preprocessors) and M4.7.6 M1.12.1 M1.8.3 M5.1.2

#else or #endif that correspond to #ifdef, #ifndef and #if should be described in the same file and their corresponding relationship should be expressed in comments. When you check if a macro name has already been defined using #if, use defined (macro name). Do not write as #if macro name. Do not write a defined operator used in #if and #elif using styles other than defined (macro name) or defined macro name. The #include directive shall be followed by either a <filename> or filename sequence. [Undefined 48] [MISRA 19.3] <<Define how to differentiate <> format and format in the file specification for #include.>> Do not use characters , \, , /*, and : for #include file specifications. The absolute path should not be described for #include file specification. Macros that contain operators should have the macro body and macro arguments enclosed in parentheses. C macros shall only expand to a braced initialiser, a constant, a parenthesised expression, a type qualifier, a storage class specifier, or a do-while-zero construct. [Koenig 82-84] [MISRA 19.4] Macros shall not be #defined or #undefd within a block. [MISRA 19.5] #undef shall not be used. [MISRA 19.6] Parts that are deleted by the preprocessor should also be described correctly. #line should not be used for another purpose other than automatic tool generation. (1) The # and ## preprocessor operators should not be used. [Unspecified 12] [MISRA 19.13] (2) There shall be at most one occurrence of the # or ## preprocessor operators in a single macro definition. [Unspecified 12] [MISRA 19.12]

7. Environments and others

7.1 Portability

P1.1.1

(1) Do not use functions that are not part of the C90 standards. (2) If you use a function that is not part of the C90 standards <<document the function you use and how to use it.>> All usage of implementation-defined behaviour shall be documented. [MISRA 3.1] When writing a program, if you are using characters other than those defined in C90, you should check the compiler specifications <<and regulate how to use them.>> Use only escape sequences defined in the language standard. If you are using a program written in other language, <<you should document its interface and define how to use it.>> When you are calling assembly language programs from C language, <<regulate how to localize them >> such as expressing them as C language functions that contain inline assembly language only or describe them using macros. For keywords extended by implementations, <<regulate macros>> and localize them. Macro functions should be used only in places related to speed capability. Do not perform operations that do not change within an iterated process. Use structure pointers as function arguments rather than structures. <<Determine and regulate the selection policy regarding whether to use the switch statement or the if statement taking readability and efficiency into consideration. >> <<Regulate the coding style for debugging when the debug option is set, and the coding style to write logs in the release module. >> (1) Do not use dynamic memories. (2) If you use dynamic memories, <<regulate the upper limit of used memories, how to handle insufficient memories, and how to debug.>>

P1.1.2 P1.2.1

P1.2.2 P1.1.3 P2.1.1

P2.1.2 7.2 Capability E1.1.1 E1.1.2 E1.1.3 E1.1.4

7.3 Debugging description 7.4 Others

M5.1.1 M5.2.1

(p.159) Appendix C: Implementation-defined functions template If you are using implementation-defined functions you need to document specifications of the implementation you apply. The following table is a template for documentation. Implementation name: C language standard implementation-defined items No. Category Content (Quoted from C90. C90 section number is shown in parentheses) 1 2 3 Diagnostic message Startup Interactive device How to identify diagnostic messages (5.1.1.3) Meaning of main function arguments (5.1.2.2.1) What the interactive device consists of (5.1.2.3) Relate d rules Usage Usage Purpose Specification of target implementation (if the usage column is ticked clearly state the specification)

Tick if used

P1.1.2 P1.1.2 P1.1.2

Mostly descriptions are not required. (It is not an issue) Using main function arguments. In most cases descriptions are not required.

4 5 6

Identifying names

The leading string (containing 31 or more characters) that carries a meaning in the identifier that is not of external linkage (6.1.2) The leading string (containing 6 or more characters) that carries a meaning in the identifier of external linkage (6.1.2)

P1.1.2

Assigning names that are over 32 characters. (C90 regulates that external identifiers up to 5 need to be able to identify letters. compilers not characters current implementations and C99 states that external 31 identifiers meaningful should have at least characters. Therefore, operation verification implementation external of is However, that do 31 in

( ) characters ( ) characters

P1.1.2

there are very few support

required only when identifiers also contain 32 or Whether differentiating English lower case and upper case in external linkage identifier is significant or not (6.1.2) P1.1.2 more characters) Required (note the difference of the upper and lower case in the naming convention) Reference: In C99, they should differentiate in the language standard. Differentiate Do not differentiate

7 8 9 10 11 12 13

Source and execution characters

Elements of execution other than defined in (5.2.1)

the source and character set those explicitly this standard

P1.2.1

Using characters other than the basic source character set or basic execution character set. Note: The basic source character set includes the upper and lower cases of 26 alphabet letters, decimal digits, 29 graphic horizontal vertical tabs controlling characters indicating format feeding. The basic execution character set consists of the basic source character set plus the five controlling characters (\0, \a, \b, \r and \n). This when writing item you applies are characters tabs, and (!, etc), spaces,

Example: Source character: Japanese characters, encoding is SJIS Execution character: Japanese characters, encoding is EUC

Japanese

Shift status used for coding multibyte characters (5.2.1.2)

P1.1.2

Numbers of bits in characters in the execution character set (5.2.4.2.1) Matching elements in the source character set and

P1.1.2

comments. It is not required if used characters (execution characters) are specified in 7 above. Mostly 8bit. State if it is 16bit. No. 7 mostly explains regarding

8bit 16bit Others ( )

P1.1.2

14 15 16

Data range

type

Whether a simple (without sign specification) char should have the same value range as the signed char or unsigned char (6.2.1.1) The style and value set of different types of integers (6.1.2.5) The result in which the value cannot be expressed when an integer is converted into a shorter signed integer or when an unsigned integer is converted into a signed integer of the same length. (6.2.1.2)

P1.1.2

Using a simple char.

The same as the signed char The same as the unsigned char To be described (1) Converting to shorter signed type Bit sequence image remains the same (higher-order bits are truncated) Others ( ) Converting Bit from sequence unsigned to signed image remains the same Others ( ) To be described (2)

P2.1.3 P1.1.2

Required. Performing conversions to shorter signed types or from unsigned to signed of equal length.

17 18 19

Operation result

Result of executing bitwise operations (~, <<, >>, &, ^, |) against a signed integer (6.3) Sign of the remainder of the integer division (6.3.5)

R2.6.2

P1.1.2

The result of a right shift of the signed integral type with negative value (6.3.7)

R2.5.4

Applying bitwise operations (~, <<, >>, &, ^, |) to signed integers. Calculating division (/) or remainder (%) against negative values (C99 defines that the result of divisions are not implementation dependent but truncated toward 0). Applying a right shift to the negative signed integral type.

Matches to the dividend (the result of division is truncated toward 0) Matches to the divisor Others ( )

20 21 22

Floating-points

23

size_t

24

Type conversion (pointers and integers)

How to express various types of floating-point numbers and collection of values (6.1.2.5) Direction of truncation when an integral value is converted into a floatingpoint number which cannot be expressed accurately against the original value (6.2.1.3) Direction of truncation when the value of a floating point is converted to a narrower floating-point number (6.2.1.4) The integer type required to retain the maximum value for the array size. That is, sizeof operator type size_t (6.3.3.4, 7.1.1) Result of when a pointer is cast to an integer and vice versa (6.3.4)

R2.1.1 R2.1.2

Using points.

floating

P1.1.2

Using size_t.

unsigned int int Others ( )

R2.7.1

Using the cast between a pointer and an integer.

1. pointer -> integer Retain bits Others ( ) 2. integer -> pointer Retain bits Others ( ) unsigned int int Others ( )

25

ptrdiff_t

26

Register specification Accessing union members Boundary alignment structure members for

27

28

The integer type required to retain the difference between pointers to two elements in the same array. That is, ptrdiff_t The range in which you can actually place objects in the register by using the register storage-class specifier When accessing union object members using a member of a different type (6.3.2.3) Filling and boundary adjustment for structure members (6.5.2.1). This is not an issue unless binary data written in one implementation is read in another implementation.

P1.1.2

Using ptrdiff_t.

P1.1.2

Using register specification. Essentially prohibited. The structure is used and it is possible that its binary data is read in other implementations. (Note: It is assumed that there is no memory overlay. If you are using

M1.6.2

R2.1.3

29 30 31

Bit fields

Whether a simple (without sign specification) int bit field should be treated as a signed int bit field or an unsigned int bit field (6.5.2.1) Allocation order of bit fields within the unit (6.5.2.1) Whether bit fields can be allocated striding across the storage unit boundary (6.5.2.1)

P1.3.3

overlay it should be stated) Using int bit fields without sign specification.

signed int unsigned int

P1.3.3

Using bit fields in a way that the bit locations in the data carry a meaning. (Note: It is assumed that there is no memory overlay. If you are using overlay it should be stated) Using the enumeration type. Using the volatile specification. In most cases descriptions are not required. (There are very few implementations that do not have enough declarators to cause a problem) In most cases descriptions are not required. (There are very few implementations that do not have enough number of cases to cause a problem)

Higher-order lower-order Lower-order higher-order

to to

Stride across the boundary Allocate to the next unit int Others ( )

32

enum type

33 34

Accessing volatile Maximum number of declarators

The integer type to be selected to express enumeration values (6.5.2.2) How to construct an access to the volatile qualified type (6.5.3) The maximum number of declarators that qualify arithmetic, structure or union types (6.5.4)

P1.3.2

P1.1.2 P1.1.2

35

Maximum case numbers

Maximum number of cases in the switch statement (6.6.4.2)

P1.1.2

36

Character constant conditional inclusions

in

Whether the value of the character constant that consists of a single character in the constant expression that controls conditional inclusion matches the value of the same character constant in the execution character set. Whether such a character constant can be negative or not. (6.8.1)

P1.1.2

Using a character constant that consists of a single character in constant expressions in the conditional inclusion.

37 38 39

Source file inclusion (#include)

How to locate source files that can be included (6.8.2) Note) This item is assumed to be applied to <> Locating names of source files that can be included enclosed in . (6.8.2) Matching source file names and strings (6.8.2)

P1.4.2

Required. unused) .

(Rarely

How to search for #include files specified with <>. Example: Search 1. 2. regulated system Example: Search 1. in the following order.

P1.4.2 P1.4.2

Directories Directories in the

specified by option.

in

the that

following order. Directories contain source files. 2. The same method as <> Example: Specify according to 40 41 #pragma _DATE_, _TIME_ The behavior of a recognized #pragma directive (6.8.6) Defining _DATE_ and _TIME_ when translation date and translation time are invalid (6.8.8) P1.1.2 P1.1.2 Using #pragma. It is likely that this function is rarely used. If you are using it the letters. To be described (3)

you should state as such. (1) Basic types, pointers <<See the rule P2.1.3. Define situations (including defining if there is any such situation) where the basic types are not used in the project, giving a brief explanation. If the project does not define another type name for the type defined by the language, delete the leading type name column.>> Project defined name C language type char signed char unsigned char short unsigned short int unsigned int long unsigned long pointer (2) Behavior of bitwise operators against signed data Bitwise operator Behavior ~ << & ^ | (3) List of #pragma Indicate pragma that can be used in the project. pragma name Function overview Number of bits Minimum value Maximum value Boundary alignment

type

(p.167)

References
[1] ISO/IEC 9126:2001, Software engineering -- Product quality - Part 1 : Quality model [2] ISO/IEC 9899:1990, Programming languages -- C ISO/IEC 9899:1990/Cor 1:1994 ISO/IEC 9899:1990/Cor 2:1996 ISO/IEC 9899:1990/Amd 1:1995, C Integrity [3] ISO/IEC 9899:1999, Programming languages C ISO/IEC 9899/Cor1:2001 [4] ISO/IEC 14882:2003, Programming languages -- C++ [5] "MISRA Guidelines For The Use Of The C Language In Vehicle Based Software", Motor Industry Software Reliability Association, ISBN 0-9524156-9-0, Motor Industry Research Association, Nuneaton, April 1998 See www.misra-c.com [6] "MISRA Guidelines For The Use Of The C Language In Vehicle Based Software", Motor Industry Software Reliability Association, ISBN 0-9524156-9-0, Motor Industry Research Association, Nuneaton, April 1998 See www.misra-c.com [7] "MISRA Guidelines For The Use Of The C Language In Vehicle Based Software", Motor Industry Software Reliability Association, ISBN 0-9524156-9-0, Motor Industry Research Association, Nuneaton, April 1998 [8] "comp.lang.c Frequently Asked Questions", http://www.eskimo.com/scs/C-faq/top.html [9] MISRA-C for Embedded Software Developers Guide for Highly-Reliable Embedded Software Programming Compiled by MISRA-C Workgroup, ISBN 4-542-50334-8, Japanese Standards Association, May 2004 [10] "GNU coding standards", Free Software Foundation, http://www.gnu.org/prep/standards/ [11] "The C Programming Language, Second Edition", Brian W. Kernighan and Dennis Ritchie, ISBN 0-13-110362-8, Prentice Hall PTR, March 1988 [12] "Writing Solid Code: Microsoft's Techniques for Developing Bug-Free C Programs", Steve Maguire, ISBN 1-55615-551-4, Microsoft Press, May 1993

[13] "The Practice of Programming", Brian W. Kernighan and Rob Pike, ISBN 0-201-61586X, Addison Wesley Professional, Feb 1999 [14] "Linux kernel coding style", http://www.linux.or.jp/JF/JFdocs/kerneldocs-2.2/CodingStyle.html [15] "C Style: Standards and Guidelines : Defi ning Programming Standards for Professional C Programmers", David Straker, ISBN 0-1311-6898-3, Prentice Hall, Jan 1992 [16] " C Programming FAQs : Frequently Asked Questions ", ISBN0-2018-4519-9, Steve Summit [17] " C STYLE GUIDE (SOFTWARE ENGINEERING LABORATORY SERIES SEL-94-003) ", NASA, Aug 1994, http://sel.gsfc. nasa.gov/website/documents/online-doc/94-003.pdf [18] TP-01002:2005, Automobile C Language Guideline (Second edition), Standardization Board, Society of Automotive Engineers of Japan

(p.168)

Authors
[]

Editor
[]

S-ar putea să vă placă și