C CODING STANDARDS AND PRACTICES ENTC 489 EMBEDDED REAL TIME SOFTWARE DEVELOPMENT REVISION 1.0 CODESTD.DOC JANUARY 15, 2015
C Coding Standards and Practices Page 2 TABLE OF CONTENTS 1. Introduction...2 2. Files...3 3. Commenting...3 4. Naming...3 5. Layout Style...3 6. Usage...4 7. Standard Headers...5 7.1 C File Headers...5 7.2 Include File Headers...5 7.3 Doxygen Main Application Description...5 7.4 Doxygen Documentation Section Identification...6 7.5 Function Headers...6 8. Constructs...6 8.1 if, if...else...6 8.2 while...7 8.3 for...7 8.4 do...while...7 8.5 switch...case...8 1. INTRODUCTION This document provides the C Language standards and practices for ENTC-489 Embedded Real Time Software Development. All software and firmware developed for that class will conform to this standard. All code must be readable and understandable. These standards were developed with the following points in mind. Where there are areas not covered by this standard use these corner posts as a guide. If there is a conflict, compromise towards readability. This coding standard is a subset of the Paragon Innovations, Inc. C coding standards. Used with permission. 1. Keep it simple. Break down complexity into simpler chunks. Clearly comment necessary complexity. 2. Be explicit. Avoid implicit or obscure features of the language. Say what you mean. 3. Be consistent. Use the same rules as broadly as possible. 4. Minimize scope. This includes logical and visual scope. Be more explicit about items with wider scope. 5. Think. "Using the latest tools and techniques does not relieve you of the responsibility to use your head." - Brian Kernighan 6. Do not use these standards as an excuse for writing bad code. If you must deviate from these standards, do so within their spirit.
C Coding Standards and Practices Page 3 2. FILES 1. Keep files less than 1000 lines (about 20 pages). 2. Make files functionally cohesive. 3. Do not define a function in a header file. 3. COMMENTING 1. Make every comment count (but do not use this as an excuse for under commenting). Don't explain what the code says, rather explain the purpose behind the code! 2. Keep code and comments visually separate. 3. Use header comments for all files and functions. 4. Use block comments regularly. 5. Comments should not extend beyond column 130. 6. Every autonomous piece of code ( e.g. loops, major blocks, switches ) should be preceded by a block comment. 7. Prefer to use Doxygen compatible comments to produce program documentation. 8. Keep comments consistent with code. 4. NAMING 1. Use abbreviations consistently, and document common usage. 2. Use two or three letters plus underscore to show functional prefixes (e.g. io_printer_init) The I/O subsystem or task is prefixed with "io". Document any prefixes used and their meanings. 3. Use between two and 30 characters per name. Use longer names for items with wider scope. 4. Name functions with verb-noun (e.g. process_variable); name variables with nounabstract-noun (e.g. wall_height). Names should be suggestive of what they represent. 5. Use all upper case for #defines, typedefs, struct tags and enum tags. 6. Avoid misspelling and sound alike spellings in variable names and comments. 7. Do not use names that differ only by case, e.g.: Error and error. 5. LAYOUT STYLE 1. Use vertical alignment to help keep layout clean. 2. Separate code 'chunks' with blank lines or comments! 3. Do not use spaces within object references. Do not space between unary operator and operand (but space on either side). Balance spacing around binary operators. DO value = PtrVar->element FltVal = 2.15 + -VarName FltVal = 2.15 + (-VarName) /* BETTER! */ Val1 = Add + And - Subtract DO NOT value = PtrVar -> element FltVal = 2.15 + - VarName Val1 = Add+And - Subtract 4. Use parentheses to emphasize chunks in expressions.
C Coding Standards and Practices Page 4 5. See Layout Templates below for examples and further standards 6. USAGE 1. Use the appropriate construct for the appropriate situation. 2. Avoid deep nesting (of statements, parentheses and structures). Aim for a normal maximum of three levels (deeper excursions should be short and infrequent). 3. Use casts to maintain type in expressions, assignments and parameters. 4. Make case statements short and independent of one another (use a break or a comment documenting fall-through at the end of each.) Always use a default. Avoid fall-through. 5. Never use the goto statement. 6. Use break to escape a loop under abnormal, rather than normal, conditions. 7. Avoid multiple returns from a function. Multiple returns are acceptable only when dealing with exceptions or errors. 8. Never use setjmp() and longjmp(). 9. Never use abort or exit. 10. Always use full ANSI function prototyping. 11. Avoid functions with large numbers of parameters. 12. Match the type of actual and formal parameters (possibly using casts). 13. DO NOT re- #define the language. 14. Minimize macro usage, especially clever usage. Parenthesize parameters and the overall expression. 15. Do not use register variables. 16. Avoid using floating point arithmetic. 17. Do not compare floating point numbers for equality (use <, >, <= or >=)! 18. Use typedef over #define or struct Tag... 19. Do typedef common types, but do not over-use. 20. Minimize use of global data. Rather, hide data with, or in owning functions. 21. Use array indexing over pointers into arrays when possible. 22. Use 0 for the NULL pointer. Always use the form (cast type) 0 in function parameters. 23. Always cast pointers when moving between types. 24. Never use 'magic numbers' - always #define or enum. (Exception: simple usage, such as initializing a count to 0 or 1.) 25. The tab character must NOT be used in any source file. Use 4 spaces as the standard indentation increment! 26. Within the entire program, variable names must not differ in letter case only. 27. Prefer the use of zero as an indication of success and non-zero values to indicate exception type for functions returning a status/success value. 28. Prefer the use of zero as an error indication for functions returning pointers. 29. Always provide boundary checking when out of range values are possible. 30. Always use sentries (see 7.2) in include files to prevent multiple declarations. 31. Do not use conditional the expression ( a = b? c : d ) as a substitute for an if statement.
C Coding Standards and Practices Page 5 7. STANDARD HEADERS 7.1 C File Headers /************************************************** * Texas A&M University * Electronic Systems Engineering Technology * ENTC-489 Embedded Real Time Software Development * Author: John Q Student * File: filename.c /*! \file * File Contents Description 7.2 Include File Headers /************************************************** * Texas A&M University * Electronic Systems Engineering Technology * ENTC-489 Embedded Real Time Software Development * Author: John Q Student * File: filename.c /*! \file * File Contents Description #ifndef _FILENAME_H #define _FILENAME_H #endif 7.3 Doxygen Main Application Description / /*! \mainpage * * Description of program *************************************************/
C Coding Standards and Practices Page 6 7.4 Doxygen Documentation Section Identification / /*! \addtogroup DOCGROUP * Description of DOCGROUP * @ */ / / /*! @ * Close of Doxygen group DOCGROUP 7.5 Function Headers / /*! Description of program * \param PARMS * \return RETURNS * \note * \see * \brief xxx_xxxx( xxxx ) /* xxxx () */ 8. CONSTRUCTS 8.1 if, if...else if ( expression ) if ( expression ) else
C Coding Standards and Practices Page 7 if ( expression ) else if ( expression ) else 8.2 while while ( expression ) /* while loop description */ while (1) /* infinite loop */ /* while loop description */ 8.3 for for( expression; expression; expression ) /* for loop description */ 8.4 do...while do /* until xyz happens */ while( expression );
C Coding Standards and Practices Page 8 8.5 switch...case switch ( expression ) case VALUE1: break; case VALUE2: /************** FALLTHROUGH **************/ case VALUE3: case VALUE4: break; default: break; /* end switch ( expression ) */