User Tools

Site Tools


coding_standards

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
coding_standards [2019/04/08 20:11]
127.0.0.1 external edit
coding_standards [2019/06/11 14:18] (current)
hutch
Line 18: Line 18:
   * Use ''#​define''​ for all scalar constants. You may use the constants ''​0''​ and ''​1''​ in if-expressions,​ for-loop expressions and while-loop expressions. You may also use ''​0''​ or ''​1''​ in arithmetic expressions.   * Use ''#​define''​ for all scalar constants. You may use the constants ''​0''​ and ''​1''​ in if-expressions,​ for-loop expressions and while-loop expressions. You may also use ''​0''​ or ''​1''​ in arithmetic expressions.
   * Use ''​static const''​ arrays if you need to hard-code test data (or otherwise initialize an array), e.g., ''​static const uint16_t testData[] = {1, 2, 3, 4};'',​ or if you need to declare some series of constant values as an array.   * Use ''​static const''​ arrays if you need to hard-code test data (or otherwise initialize an array), e.g., ''​static const uint16_t testData[] = {1, 2, 3, 4};'',​ or if you need to declare some series of constant values as an array.
 +  * Use #define for all string constants EXCEPT when the string contains a printf formatting directive (%d, etc.).
   * Your code, when submitted, must be in a finished form. You are allowed a total of 5 lines of "​commented-out"​ code per file.   * Your code, when submitted, must be in a finished form. You are allowed a total of 5 lines of "​commented-out"​ code per file.
   * You must have at least an 50% comment-to-code ratio. If you have 10 lines of code, you must have at least 5 lines of comments. A comment "​line"​ can either be on its own line or start at the end of the source-code line. Either counts as a "​line"​ of comment code.   * You must have at least an 50% comment-to-code ratio. If you have 10 lines of code, you must have at least 5 lines of comments. A comment "​line"​ can either be on its own line or start at the end of the source-code line. Either counts as a "​line"​ of comment code.
Line 34: Line 35:
   * "​.c"​ files contain code.   * "​.c"​ files contain code.
   * All function names and constant values contained in .h files must be prefixed by the base-name of the file + underscore, e.g., ''​buttons_read()'',​ ''#​define BUTTONS_BTN0_MASK 0x1''​. Function names and constant values that are used only within .c files do not need to be prefixed by the base-name of the file.    * All function names and constant values contained in .h files must be prefixed by the base-name of the file + underscore, e.g., ''​buttons_read()'',​ ''#​define BUTTONS_BTN0_MASK 0x1''​. Function names and constant values that are used only within .c files do not need to be prefixed by the base-name of the file. 
-  * All single ​constant values must be defined using #define and anything defined by a ''#​define''​ must use all uppercase letters. ​+  * All scalar ​constant values must be defined using #define and anything defined by a ''#​define''​ must use all uppercase letters ​in its name
   * Use the ''​const''​ key word only if you are defining an array of constant values, e.g., ''​const int foo[2] = {1, 2};''​   * Use the ''​const''​ key word only if you are defining an array of constant values, e.g., ''​const int foo[2] = {1, 2};''​
-  * The constants ''​0''​ and ''​1''​ can be used without a ''#​define''​ within if-expressions,​ and while- and for-loops, e.g., ''​for (int16_t i=0;​)'',​ ''​if (i==0)'',​ and ''​while (1)''​. You can use '​1'​ and '​0'​ to initialize variables. You can also use ''​0''​ and ''​1''​ in arithmetic expressions. No other exceptions are allowed. See the code below for examples of how to use '​1'​ and '​0'​.+  * The constants ''​0''​ and ''​1''​ can be used without a ''#​define''​ within if-expressions,​ and while- and for-loops, e.g., ''​for (int16_t i=0;​)'',​ ''​if (i==0)'',​ and ''​while (1)''​. You can use '​1'​ and '​0'​ to initialize variables. You can also use ''​0''​ and ''​1''​ in assignment or arithmetic expressions. No other exceptions are allowed. See the code below for examples of how to use '​1'​ and '​0'​
 +  * You don't have to use your #define for strings ONLY if the string contains a printf formatting directive (%d, etc).
   * ''#​define''​ names should be meaningful, e.g., ''#​define TEN 10''​ may sound clever but you will lose points if you use ''#​define''​ this way.   * ''#​define''​ names should be meaningful, e.g., ''#​define TEN 10''​ may sound clever but you will lose points if you use ''#​define''​ this way.
   * Use proper and consistent indention techniques.   * Use proper and consistent indention techniques.
Line 69: Line 71:
 A good but rather detailed discussion of this topic can be found at: [[http://​www.cprogramming.com/​declare_vs_define.html|declaration versus definition]]. A good but rather detailed discussion of this topic can be found at: [[http://​www.cprogramming.com/​declare_vs_define.html|declaration versus definition]].
  
-==== Example ===== 
-"​circularBuffer.h"​ and "​circularBuffer.c"​ are provided below as examples of files that follow the coding standard for this class. For this example, "​circularBuffer"​ is the base-name. Thus the "​.c"​ file is named "​circularBuffer.c"​ and the "​.h"​ file is named "​circularBuffer.h"​. These are a couple of files that I never finished so they have not been debugged and some functions have not been completely implemented. They are typical of my commenting style. To give you an idea of how to count lines of comments and lines of code, circularBuffer.h contains 13 lines of code (I don't count the ifndef for the .h file) and 13 lines of comments. circularBuffer.c contains about 25 lines of code and 30 lines of comments. I don't count braces on empty lines as code lines. 
- 
-You will see legal examples of '​1'​ and '​0'​ used as constants in the code below. 
- 
-Note that this code was never tested so only use it as an example of commented code. Accordingly,​ it does not contain init() or runTest() functions. 
- 
-<code C> 
-#ifndef CIRCULARBUFFER_H_ 
-#define CIRCULARBUFFER_H_ 
- 
-#include <​stdint.h>​ 
-#include <​stdbool.h>​ 
- 
-// Keep things integer powers of 2 so that address calculations are fast. 
-#define CIRCULAR_BUFFER_INDEX_MASK 0xFF 
- 
-// The data-structure that will hold the circular-buffer. 
-typedef struct { 
- uint32_t writeIndex;​ //​ You write new data here. 
- uint32_t readIndex;​ //​ You read data from here. 
- bool wrapAroundFlag;​ //​ True if you have rolled over. 
- bool firstPassFlag;​ //​ True if this is your first write pass through the array. 
- uint32_t *data; // Data are stored here. 
-} circularBuffer_t;​ 
- 
-// Init's the buffer to the empty state, allocating fresh memory. 
-void circularBuffer_init(circularBuffer_t* cb); 
- 
-// Just resets the index pointers to start at the zero position, and resets the overflow flag. 
-void circularBuffer_reset(circularBuffer_t* cb); 
- 
-// Adds a new data item to the buffer. 
-void circularBuffer_addData(circularBuffer_t* cb, uint32_t datum); 
- 
-// Reads a data item at the given index. The index is relative, an index of 0 just means the first (oldest) 
-// element of the circular buffer. 
-uint32_t circularBuffer_readDataAt(circularBuffer_t* cb, uint32_t index); 
- 
-// Returns the number of elements contained in the buffer. 
-uint32_t circularBuffer_size(circularBuffer_t* cb); 
- 
-#endif /* CIRCULARBUFFER_H_ */ 
-</​code>​ 
- 
-<code c> 
-#include "​circularBuffer.h"​ 
-#include <​stdlib.h> ​        // I get malloc() from here. 
-#include <​stdio.h> ​         // printf(). 
- 
-// Init's the buffer to the empty state, allocating fresh memory. 
-void circularBuffer_init(circularBuffer_t* cb) { 
- circularBuffer_reset(cb); ​  // This inits all of the slots. 
- // Allocate the memory to hold the data. 
- cb->​data = (uint32_t *) malloc((CIRCULAR_BUFFER_INDEX_MASK + 1) * sizeof(uint32_t));​ 
-} 
- 
-// Just resets the index pointers to start at the zero position, and resets the overflow flag. 
-// The buffer becomes empty after reset(). 
-// Buffer must be reset prior to writing anytime it has been read. 
-void circularBuffer_reset(circularBuffer_t* cb) { 
- cb->​writeIndex = cb->​readIndex = 0; // Read and write indicies both start at 0. 
- cb->​wrapAroundFlag = false; ​        // Start out not wrapped around. 
- cb->​firstPassFlag = true;           // On your first pass through the buffer. 
-} 
- 
-// Adds a new data item to the buffer. Addressing scheme 
-// assumes that the initial data was added starting at index = 0. 
-// writeIndex always points to the location to be written and then is incremented. 
-void circularBuffer_addData(circularBuffer_t* cb, uint32_t datum) { 
- cb->​data[cb->​writeIndex] = datum; ​ // Write the data to the buffer at current write-index. 
- // Wrap around has occurred if you are back at 0 and not on your first-pass. 
- if (cb->​writeIndex == 0 && !cb->​firstPassFlag) 
- cb->​wrapAroundFlag = true; 
- // Increment the write-index ala modulo. 
- cb->​writeIndex = (cb->​writeIndex + 1) & CIRCULAR_BUFFER_INDEX_MASK;​ 
-        // Check for wrap-around and compute addresses and update the firstPassFlag. 
- if (cb->​writeIndex == 0) {         // You know that you are starting the second pass if you are back at 0. 
- cb->​firstPassFlag = false; // but don't know if you will wrap-around until next write. 
- } 
-} 
- 
-// NYI. Have not completed this function. Compiles returns bogus values when data are wrapped around. 
-// Returns the number of items in the buffer. 
-// User must call this to determine how many elements are in the buffer. 
-uint32_t circularBuffer_size(circularBuffer_t* cb) { 
- if (cb->​wrapAroundFlag) ​ //  OK, you are wrapped around, compute data-element size accordingly. 
- return CIRCULAR_BUFFER_INDEX_MASK + 1;  // NYI. Haven'​t implemented this yet. 
- else  // Not wrapped around, data are from the read-index to the write-index. ​                                           
- return (cb->​writeIndex - cb->​readIndex + 1); 
-} 
- 
-// Reads a data item at a given index. The index is relative, an index of 0 just means the first 
-// element (oldest) of the circular buffer. Index is always masked so it will always be in range. 
-// Does not check the index to see if it is accessing stored data (for speed). User is responsible 
-// to access data in range. 
-uint32_t circularBuffer_readDataAt(circularBuffer_t* cb, uint32_t index) { 
- if (cb->​wrapAroundFlag) {   // Data are indexed differently if wrapped around. 
-//​ printf("​address->​%ld\r\n",​ (cb->​writeIndex + 1 + index) & CIRCULAR_BUFFER_INDEX_MASK);​ 
-                // Return the data using modulo addressing. 
- return cb->​data[(cb->​writeIndex + 1 + index) & CIRCULAR_BUFFER_INDEX_MASK]; ​ 
- } else {    // Not wrapped around. 
-                // Don't think you need to wrap here but it doesn'​t hurt anything. 
- return cb->​data[index & CIRCULAR_BUFFER_INDEX_MASK]; ​   ​ 
- } 
-} 
- 
-</​code>​ 
 ---- ----
coding_standards.1554775915.txt.gz · Last modified: 2019/04/08 20:11 by 127.0.0.1