C Coding Standard — NuttX latest documentation (original) (raw)

NuttX follows a specific coding style which needs to be followed at all times a contribution to be accepted. Please read this document before working on new code so that you can follow the style from the start. To check your code for conformance to the coding style, you should use the checkpatch.sh script (that calls the nxstyle tool) included under tools/ in the main NuttX repository, or enable the pre-commit functionality described inpre-commit.

Quick Check for Compliance

You should check for coding style issues before submitting your Pull Request. There is a script that you can run to check for coding styles issue:

./tools/checkpatch.sh -g HEAD~...HEAD

Alternatevily you can run this script passing the .c file or .h header you want to check:

./tools/checkpatch.sh -f path/to/your/file.c

General Conventions

File Organization

File Extensions Use the .h extension for C header files and .c for C source files.

File header. Every C, C++, make file, or script begins with a file header. That file header is enclosed with a block comment (see below). Within the block comment, the following must appear:

Sample File Headers. Sample file headers are provided in anAppendix to this document. No new software may be included in the NuttX source tree that does not have licensing information included in the file. No new software may be included in the NuttX source tree that does not have a Apache 2.0 license or license (or, in the case of 3rd party file, a compatible license such as the BSD or MIT licenses). If the file does not follow Apache 2.0 licensing, then the appropriate license information should be provided in the header rather than the Apache 2.0 licensing information and a NOTE should be included in the top-level LICENSE and/or NOTICE file(s), as appropriate, to indicate any variations from Apache 2.0 licensing.

Grouping. All like components in a C source or header file are grouped together. Definitions do not appear arbitrarily through the file, rather, like definitions are grouped together and preceded by a block comment identifying the grouping.

Block Comments. Each grouping in the file is separated with a_block comment_. The block comment consists of:

Examples of Block Comments. See Appendix A for examples of block comments.

Order of Groupings. The following groupings should appear in all C source files in the following order:

  1. Included Files
  2. Pre-processor Definitions
  3. Private Types (definitions)
  4. Private Function Prototypes (declarations)
  5. Private Data (definitions)
  6. Public Data (definitions)
  7. Private Functions (definitions)
  8. Public Functions (definitions)

The following groupings should appear in all C header files in the following order:

  1. Included Files
  2. Pre-processor Definitions
  3. Public Types (definitions)
  4. Public Data (declarations)
  5. Inline Functions (definitions)
  6. Public Function Prototypes (declarations)

Large vs. Small Files. In larger files, block comments should be included for all groupings, even if they are empty; the empty grouping provides important information in itself. Smaller files may omit some of the block comments; it is awkward if the block comments are larger than the file content!

Header File Idempotence. C header file must protect against multiple inclusion through the use of macros that “guard” against multiple definitions if the header file is included multiple times.

#ifndef __INCLUDE_NUTTX_ARCH_H
#define __INCLUDE_NUTTX_ARCH_H
Notice that the definitions within of the header do not follow the usually rules: The presence of the conditional test at the top of the file does not cause the remaining definitions within the file to be indented.

#endif /* __INCLUDE_NUTTX_ARCH_H */

Forming Guard Names. Then pre-processor macro name used in the guard is formed from the full, relative path to the header for from the top-level, controlled directory. That path is preceded by__ and _ replaces each character that would otherwise be invalid in a macro name. So, for example, __INCLUDE_NUTTX_ARCH_Hcorresponds to the header file include/nuttx/arch.h

Deoxygen Information. NuttX does not use Deoxygen for documentation and no file should contain Doxygen tags or Doxygen style comments.

Sample File Formats. C source and header file templates are provided in an Appendix to this document.

Lines

Line Endings. Files should be formatted with the newline character (\n) as the line ending (Unix-style line endings) and specifically not the carriage return, newline sequence (\r\n) used with Windows-style line endings. There should be no extra whitespace at the end of the line. In addition, all text files should end in a single newline (\n). This avoids the_“No newline at end of file”_ warning generated by certain tools.

Line Width. Text should not extend past column 78 in the typical C source or header file. Sometimes the nature of the content of a file may require that the lines exceed this limit. This often occurs in header files with naturally long definitions. If the line width must extend 78 lines, then some wider line width may be used in the file provided that it is used consistently.

Line Wrapping.

Error

This is incorrect

struct some_long_struct_name_s { struct some_long_struct_name_s flink; / The forward link to the next instance of struct some_long_struct_name_s in a singly linked list / int short_name1; / Short comment 1 / int short_name2; / This is a very long comment describing subtle aspects of the short_name2 field */ };

struct some_medium_name_s *ptr = malloc(sizeof(some_medium_name_s);

struct some_long_struct_name_s *ptr = malloc(sizeof(some_long_struct_name_s);

ret = some_function_with_many parameters(long_parameter_name_1, long_parameter_name_2, long_parameter_name_3, long_parameter_name_4, long_parameter_name_5, long_parameter_name_6, long_parameter_name_7, long_parameter_name_8);

ret = some_function_with_many parameters(long_parameter_name_1, long_parameter_name_2, long_parameter_name_3 long_parameter_name_4, long_parameter_name_5, long_parameter_name_6, long_parameter_name_7, long_parameter_name_8);

Hint

This is correct

struct some_long_struct_name_s { /* The forward link to the next instance of struct

struct some_long_struct_name_s flink; int short_name1; / Short comment 1. / int short_name2; / This is a very long comment describing subtle * aspects of the short_name2 field. */ };

FAR struct some_medium_name_s *ptr = malloc(sizeof(some_medium_name_s);

FAR struct some_medium_name_s *ptr = malloc(sizeof(some_medium_name_s);

FAR struct some_long_struct_name_s *ptr = malloc(sizeof(some_long_struct_name_s);

ret = some_function_with_many parameters(long_parameter_name_1, long_parameter_name_2, long_parameter_name_3, long_parameter_name_4, long_parameter_name_5, long_parameter_name_6, long_parameter_name_7, long_parameter_name_8);

NOTE: See the discussion of pointers for information about the FAR qualifier used above.

Double Spacing. A single blank line may be use to separate logical groupings as the designer feels fit. Single blank lines are also required in certain contexts as defined in this standard. Additional blanks lines (two or more) are prohibited.

Columnar Organization. Similar things should be aligned on the same column unless doing so would cause the line width to be exceeded.

Note

This is acceptable

dog = cat; monkey = oxen; aardvark = macaque;

Hint

This is preferred

dog = cat; monkey = oxen; aardvark = macaque;

Block Comments The final asterisk (*) should occur at column 78 (or the line width of files with longer lines). Note that the final comment delimiter of the block comment is an exception an lies at column 79.

Braces

In general, the use of braces in the NuttX coding standard is similar to the use of braces in the GNU Coding standards with a few subtle differences.

Coding Standard:

Error

This is incorrect

while (true) { if (valid) { ... } /* if valid / else { ... } / not valid / } / end forever */ if (a < b) { if (a < 0) { c = -a; } else { c = a; } } else { if (b < 0) { c = -b; } else { c = b; } }

Tip

This is correct

while (true) { if (valid) { ... } else { ... } }

if (a < b) { if (a < 0) { c = -a; } else { c = a; } } else { if (b < 0) { c = -b; } else { c = b; } }

Exception to Indentation Rule for Braces. The exception is braces that following structure, enumeration, union, and function declarations. There is no additional indentation for those braces; those braces align with the beginning of the definition

Error

This is incorrect

enum kinds_of_dogs_e { ... };

struct dogs_s { ... union { ... } u; ... };

struct cats_s { ... union { ... } u; ... };

int animals(int animal) { ... }

Tip

This is correct

enum kinds_of_dogs_e { ... };

struct dogs_s { ... union { ... } u; ... };

struct cats_s { ... union { ... } u; ... };

int animals(int animal) { ... }

Indentation

In general, the indentation in the NuttX coding standard is similar to the indentation requirements of the GNU Coding standards with a few subtle differences.

Indentation Unit. Indentation is in units of two spaces; Each indentation level is twos spaces further to the right than the preceding indentation levels. TAB characters may not be used for indentation.

Error

This is incorrect

if (x == y) { dosomething(x); }

if (x == y) { dosomething(x); }

Tip

This is correct

if (x == y) { dosomething(x); }

Use of TAB Characters. The use of TAB characters for indentation is prohibited in C source and header files. TAB characters are, however, used in make files, assembly language source files, Kconfig files and some script files. When TAB characters are used in these files, spaces may not be used for indentation. The correct TAB setting is 4 spaces (not 8) in these cases.

Alignment of Braces. Note that since braces must be on a separate line (see above), this indentation by two spaces has an interesting property:

Thus, all code at the indentation level should align on the same column. Similarly, opening and closing braces at the same indentation level should also align on the same (but different) column.

Indentation of Pre-Processor Lines. C Pre-processor commands following any conditional computation are also indented following basically the indentation same rules, differing in that the # always remains in column 1.

When C pre-processor statements are indented, they should be should be indented by 2 spaces per level-of-indentation following the #. C pre-processor statements should be indented when they are enclosed within C pre-processor conditional logic (#if..#endif). The level of indentation increases with each level of such nested conditional logic.

C pre-processor statements should always be indented in this way in thePre-processor Definitions section of each file. C pre-processor statements may be indented in thePublic/Private Data and Public/Private Functions sections of the file. However, often the indentation of C pre-processor statements conflicts with the indentation of the C code and makes the code more difficult to read. In such cases, indentation of C pre-processor statements should be omitted in those sections (only).

Error

This is incorrect

#ifdef CONFIG_ABC #define ABC_THING1 1 #define ABC_THING2 2 #define ABC_THING3 3 #endif

#ifdef CONFIG_ABC #define ABC_THING1 1 #define ABC_THING2 2 #define ABC_THING3 3 #endif

Tip

This is correct

#ifdef CONFIG_ABC

define ABC_THING1 1

define ABC_THING2 2

define ABC_THING3 3

#endif

#ifdef CONFIG_ABC

define ABC_THING1 1

define ABC_THING2 2

define ABC_THING3 3

#endif

Exception. Each header file includes idempotence definitions at the beginning of the header file. This conditional compilation does not cause any change to the indentation.

Error

This is incorrect

#ifndef __INCLUDE_SOMEHEADER_H

define __INCLUDE_SOMEHEADER_H

...

define THING1 1

define THING2 2

define THING3 3

... #endif /* __INCLUDE_SOMEHEADER_H */

Tip

This is correct

#ifndef __INCLUDE_SOMEHEADER_H #define __INCLUDE_SOMEHEADER_H ... #define THING1 1 #define THING2 2 #define THING3 3 ... #endif /* __INCLUDE_SOMEHEADER_H */

Parentheses

Coding Standard:

Error

This is incorrect

int do_foobar ( void ) { int ret = 0; int i;

for( i = 0; ( ( i < 5 ) || ( ret < 10 ) ); i++ ) { ret = foobar ( i ); }

return ( ret ); }

Tip

This is correct

int do_foobar(void) { int ret = 0; int i;

for (i = 0; i < 5 || ret < 10; i++) { ret = foobar(i); }

return ret; }

NOTE: Many people do not trust their understanding of the precedence of operators and so use lots of parentheses in expressions to force the order of evaluation even though the parentheses may have no effect. This will certainly avoid errors due to an unexpected order of evaluation, but can also make the code ugly and overly complex (as in the above example). In general, NuttX does not use unnecessary parentheses to force order of operations. There is no particular policy in this regard. However, you are are advised to check your C Programming Language book if necessary and avoid unnecessary parenthesis when possible.

Data and Type Definitions

One Definition/Declaration Per Line

Error

This is incorrect

extern long time, money; char **ach, *bch; int i, j, k;

Tip

This is correct

extern long time; extern long money; FAR char **ach; FAR char *bch; int i; int j; int k;

NOTE: See the discussion of pointers for information about the FAR qualifier used above.

Global Variables

Global vs. Local vs. Public vs. Private By a global variable it is meant any variable defined outside of a function. The distinction is between this kind of global and function local definition and refers to the scope a symbol within a file. A related concept for all_global_ names defined within a file is the scope of the name across different files. If the global symbol is prepended with the staticstorage class then the scope of the global symbol is within the file only. This is a somewhat different concept and within NuttX you will find these distinguished as private vs. public global symbols. However, within this standard, the term global variable will refer to any variable that has more than local scope.

Coding Standard:

Error

This is incorrect

extern int someint; static int anotherint; uint32_t dwA32BitInt; uint32_t gAGlobalVariable;

Note

This is acceptable

extern int g_someint; static int g_anotherint; uint32_t g_a32bitint; uint32_t g_aglobal;

Tip

This is preferred

struct my_variables_s { uint32_t a32bitint; uint32_t aglobal; };

extern int g_someint; static int g_anotherint; struct my_variables_s g_myvariables;

Parameters and Local Variables

Coding Standard:

Error

This is incorrect

uint32_t somefunction(int a, uint32_t dwBValue) { uint32_t this_is_a_long_variable_name = 1; int i;

for (i = 0; i < a; i++) { this_is_a_long_variable_name *= dwBValue--; }

return this_is_a_long_variable_name; }

Tip

This is correct

uint32_t somefunction(int limit, uint32_t value) { uint32_t ret = 1; int i;

for (i = 0; i < limit; i++) { ret *= value--; }

return ret; }

NOTE: You will see the local variable named ret is frequently used in the code base for the name of a local variable whose value will be returned or to received the returned value from a called function.

Type Definitions

Coding Standard:

Error

This is incorrect

typedef void *myhandle; typedef int myInteger;

Tip

This is correct

typedef FAR void *myhandle_t; typedef int myinteger_t;

NOTE: See the discussion of pointers for information about the FAR qualifier used above.

Structures

Structure Naming

Structure Field Naming

Other Applicable Coding Standards. See sections related to line formatting, use of braces,indentation, and comments.

Size Optimizations. When declaring fields in structures, order the declarations in such a way as to minimize memory waste due of data alignment. This essentially means that that fields should be organized by data size, not by functionality: Put all pointers together, alluint8_t’s together, all uint32_t’s together. Data types withi well known like uint8_t and uint32_t should also be place in either ascending or descending size order.

Error

This is incorrect

typedef struct /* Un-named structure / { ... int val1, val2, val3; / Values 1-3 */ ... } xzy_info_t;

struct xyz_information { ... uint8_t bita : 1, /* Bit A / bitb : 1, / Bit B / bitc : 1; / Bit C */ ... };

struct abc_s { ... struct { int a; /* Value A / int b; / Value B / int c; / Value C / }; / Un-named structure field */ ... };

Tip

This is correct

struct xyz_info_s { ... int val1; /* Value 1 / int val2; / Value 2 / int val3; / Value 3 */ ... };

Warning

This is discouraged

typedef struct xyz_info_s xzy_info_t;

The use of typedef’ed structures is acceptable but discouraged.

Tip

This is correct

struct xyz_info_s { ... uint8_t bita : 1, /* Bit A / uint8_t bitb : 1, / Bit B / uint8_t bitc : 1, / Bit C */ ... };

Warning

This is discouraged

struct abc_s { ... struct { int a; /* Value A / int b; / Value B / int c; / Value C */ } abc; ... };

The use of structures defined within other structures is acceptable provided that they define named fields. The general practice of defining a structure within the scope of another structure, however, is still but discouraged in any case. The following is preferred:

Tip

This is preferred

struct abc_s { ... int a; /* Value A / int b; / Value B / int c; / Value C */ ... };

Unions

Union and Field Names. Naming of unions and fields within unions follow the same naming rules as for structures and structure fields. The only difference is that the suffix _uis used to identify unions.

Other Applicable Coding Standards. See sections related to line formatting, use of braces,indentation, and comments.

Note

This is acceptable

union xyz_union_u /* All unions must be named / { uint8_t b[4]; / Byte values. / uint16_t h[2]; / Half word values. / uint32_t w; / Word Value. */ };

typedef union xyz_union_u xzy_union_t;

The use of typedef’ed unions is acceptable but discouraged.

Tip

This is preferred

struct xyz_info_s { ... union { uint8_t b[4]; /* Byte values. / uint16_t h[2]; / Half word values. / uint32_t w; / Word Value. / } u; / All union fields must be named */ ... };

NOTE: Note that the union fields within structures are often namedu. This is another exception to the prohibition against using single character variable and field names. The short field name u clearly identifies a union field and prevents the full name of the union value from being excessively long.

Enumerations

Enumeration Naming. Naming of enumerations follow the same naming rules as for structure and unionnaming. The only difference is that the suffix _e is used to identify an enumeration.

Enumeration Value Naming. Enumeration values, however, following a naming convention more similar to macros.

Other Applicable Coding Standards. See sections related to line formatting, use of braces,indentation, and comments.

Tip

This is correct

enum xyz_state_e { XYZ_STATE_UNINITIALIZED = 0, /* Uninitialized state. / XYZ_STATE_WAITING, / Waiting for input state. / XYZ_STATE_BUSY, / Busy processing input state. / XYZ_STATE_ERROR, / Halted due to an error. / XYZ_STATE_TERMINATING, / Terminating stated. / XYZ_STATE_TERMINATED / Terminating stated. */ };

C Pre-processor Macros

Coding Standard:

Macro Naming. Macro naming following a naming convention similar to the naming of enumeration values.

Other Applicable Coding Standards. See sections related to line formatting, indentation, andcomments.

Error

This is incorrect

#define max(a,b) a > b ? a : b

#define ADD(x,y) x + y

#ifdef HAVE_SOMEFUNCTION int somefunction(struct somestruct_s* psomething); #else #define SOMEFUNCTION() (0) #endif

define IS_A_CAT(c) ((c) == A_CAT)

#define LONG_MACRO(a,b)
{
int value;
value = b-1;
a = b*value;
}

#define DO_ASSIGN(a,b) a = b

Tip

This is correct

#define MAX(a,b) (((a) > (b)) ? (a) : (b))

#define ADD(x,y) ((x) + (y))

#ifdef HAVE_SOMEFUNCTION int somefunction(struct somestruct_s* psomething); #else

define somefunction(p) (0)

#endif

define IS_A_CAT(c) ((c) == A_CAT)

#define LONG_MACRO(a,b)
{
int value;
value = (b)-1;
(a) = (b)*value;
}

#define DO_ASSIGN(a,b) do { (a) = (b); } while (0)

Pointer Variables

Pointer Naming. Pointers following same naming conventions as for other variable types. A pointer (or pointer-to-a-pointer) variable may be prefaced with p (or pp) with no intervening underscore character _ in order to identify that variable is a pointer. That convention is not encouraged, however, and is only appropriate if there is some reason to be concerned that there might otherwise be confusion with another variable that differs only in not being a pointer.

White Space. The asterisk used in the declaration of a pointer variable or to dereference a pointer variable should be placed immediately before the variable name with no intervening spaces. A space should precede the asterisk in a cast to a pointer type.

Error

This is incorrect

int somefunction(struct somestruct_s* psomething);

ptr = (struct somestruct_s*)value;

Tip

This is correct

int somefunction(FAR struct somestruct_s *something);

ptr = (FAR struct somestruct_s *)value;

FAR

FAR, NEAR, DSEG and CODE pointers. Some architectures require a qualifier on pointers to identify the address space into which the pointer refers. The macros FAR, NEAR, DSEG and CODEare defined in include/nuttx/compiler.h to provide meaning for this qualifiers when needed. For portability, the general rule is that pointers to data that may lie in the stack, heap, .bss, or .datashould be prefaced by the qualifier FAR; pointers to functions probably lie in a code address space and should have the qualifierCODE. The typical effect of these macros on architectures where they have meaning to determine the size of the pointer (size in the sense of the width of the pointer value in bits).

Initializers

Applicable Coding Standards. See the section related toparentheses.

C89 Compatibility. All common NuttX code must conform to ANSII C89 requirements. Newer C standards permit more flexible initialization with named initializers and array initializers. However, these are not backward compatible with C89 and cannot be used in common code. Newer C99 features may be included in architecture-specific sub-directories where there is no possibility of the use of such older toolchains. C11 is included in NuttX, but has not been verified and, hence, it not encourage anywhere.

Functions

Function Naming

Coding Standard:

Parameter Lists

Coding Standards. See general rules for parameter naming. See also the sections related to the use ofparentheses.

Use of const parameters. Use of the const storage class is encouraged. This is appropriate to indicate that the function will not modify the object.

Function Body

Coding Standard:

Other Applicable Coding Standards. See sections related to General Conventions, Parameters and Local Variables, and Statements.

Error

This is incorrect

int myfunction(int a, int b) { int c, d; c = a d = b;

int e = c + d;

for (int i = 0; i &lt; a; i++)
  {
    for (int j = 0; j &lt; b; j++)
      {
        e += j * d;
      }
  }

return (e / a);

}

Tip

This is correct

int myfunction(int a, int b) { int c; int d; int e; int i;

c = a d = b; e = c + d;

for (i = 0; i < a; i++) { int j;

  for (j = 0; j &lt; b; j++)
    {
      e += j * d;
    }
}

return e / a; }

Returned Values

OS Internal Functions. In general, OS internal functions return a type int to indicate success or failure conditions. Non-negative values indicate success. The return value of zero is the typical success return value, but other successful return can be represented with other positive values. Errors are always reported with negative values. These negative values must be a well-defined errno as defined in the filenuttx/include/errno.h.

Application/OS Interface. All but a few OS interfaces conform to documented standards that have precedence over the coding standards of this document.

Checking Return Values. Callers of internal OS functions should always check return values for an error. At a minimum, a debug statement should indicate that an error has occurred. Ignored return values are always suspicious. All calls to malloc or realloc, in particular, must be checked for failures to allocate memory to avoid use of NULL pointers.

Statements

One Statement Per Line

Coding Standard:

Other Applicable Coding Standards. See the section related to the use of braces.

Error

This is incorrect

if (var1 < var2) var1 = var2;

case 5: var1 = var2; break;

var1 = 5; var2 = 6; var3 = 7;

var1 = var2 = var3 = 0;

Tip

This is correct

if (var1 < var2) { var1 = var2; }

case 5: { var1 = var2; } break;

var1 = 5; var2 = 6; var3 = 7;

var1 = 0; var2 = 0; var3 = 0;

Casts

Coding Standard:

Error

This is incorrect

struct something_s x = (struct something_s) y;

Tip

This is correct

struct something_s *x = (struct something_s *)y;

Operators

Spaces before and after binary operators. All binary operators (operators that come between two values), such as +, -, =,!=, ==, >, etc. should have a space before and after the operator, for readability. As examples:

Error

This is incorrect

for=bar; if(a==b) for(i=0;i<5;i++)

Tip

This is correct

for = bar; if (a == b) for (i = 0; i < 5; i++)

No space separating unary operators. Unary operators (operators that operate on only one value), such as ++, should not have a space between the operator and the variable or number they are operating on.

Forbidden Multicharacter Forms. Many operators are expressed as a character in combination with = such as +=, >=, >>=, etc. Some compilers will accept the = at the beginning or the end of the sequence. This standard, however, requires that the = always appear last in order to avoid ambiguities that may arise if the =were to appear first. For example, a =++ b; could also be interpreted as a =+ +b; or a = ++b all of which are very different.

if then else Statement

Coding Standard:

Other Applicable Coding Standards. See sections related to use of braces and indentation.

Error

This is incorrect

if(var1 < var2) var1 = var2;

if(var > 0) var--; else var = 0;

if (var1 > 0) { var1--; } else { var1 = 0; } var2 = var1;

Tip

This is correct

if (var1 < var2) { var1 = var2; }

if (var > 0) { var--; } else { var = 0; }

if (var1 > 0) { var1--; } else { var1 = 0; }

var2 = var1;

Ternary operator (<condition> ? <then> : <else>):

Other Applicable Coding Standards. See sections related toparentheses.

Tip

This is correct

int arg1 = arg2 > arg3 ? arg2 : arg3; int arg1 = ((arg2 > arg3) ? arg2 : arg3);

switch Statement

Definitions:

Coding Standard:

Other Applicable Coding Standards. See sections related to use of braces, indentation, andcomments.

Tip

This is correct

switch (...) { case 1: /* Example of a comment following a case selector. */ ...

/* Example of a comment preceding a case selector. */

case 2:
  {
    /* Example of comment following the case selector. */

    int value;
    ...
  }
  break;

default:
  break;

}

while Statement

Coding Standard:

Other Applicable Coding Standards. See sections related to use of braces, indentation, andcomments.

Error

This is incorrect

while( notready() ) { } ready = true;

while (*ptr != '\0') ptr++;

Tip

This is correct

while (notready());

ready = true;

while (*ptr != '\0') { ptr++; }

do while Statement

Coding Standard:

Other Applicable Coding Standards. See sections related to use of braces, indentation, andcomments.

Error

This is incorrect

do { ready = !notready(); } while (!ready); senddata();

do ptr++; while (*ptr != '\0');

Error

This is incorrect

do { ready = !notready(); } while (!ready);

senddata();

do { ptr++; } while (*ptr != '\0');

Use of goto

Coding Standard:

Tip

This is correct

FAR struct some_struct_s *ptr; int fd; int ret; ...

if (arg == NULL) { ret = -EINVAL; goto errout; } ... ptr = malloc(sizeof(struct some_struct_s)); if (!ptr) { ret = -ENOMEM; goto errout; } ... fd = open(filename, O_RDONLY); if (fd < 0) { errcode = -errno; DEBUGASSERT(errcode > 0); goto errotout_with_alloc; } ... ret = readfile(fd); if (ret < 0) { goto errout_with_openfile; } ... errout_with_openfile: close(fd);

errout_with_alloc: free(ptr);

error: return ret;

NOTE: See the discussion of pointers for information about the FAR qualifier used above.

C++

There is no existing document that provides a complete coding standard for NuttX C++ files. This section is included here to provide some minimal guidance in C++ code development. In most details like indentation, spacing, and file organization, it is identical to the C coding standard. But there are significant differences in the acceptable standard beyond that. The primary differences are as follows:

C++ style comments are not only permissible but are required (other than for the following exception). This includes the block comments of in the_Source File Structure_ described in an Appendix to this standard.

Deoxygen tags are acceptable. As are C style comments when needed to provide DOxygen tags.

There is currently no requirement to conform any specific C++ version. However, for portability reasons, conformance to older, pre-C++11 standards is encouraged where reasonable.

C++ file name extensions: The extension .cxx is used for C++ source files; the extension .hxx is used for C++ header files.

All naming must use CamelCase. Use of the underbar character, ‘_’ is discouraged. This includes variables, classes, structures, …, etc.: All user-nameable C++ elements. Pre-processor definitions are still required to be all upper case.

Local variable, method names, and function names must all begin with a lower case letter. As examples, myLocalVariable would be a compliant name for a local variable; myMethod would be a compliant name for a method;

Namespaces, global variable, class, structure, template, and enumeration names begin with a capital letter identifying what is being named:

Namespace Names

Namespaces begin with an upper case character but no particular character is specified. As an example, MyNamespace is fully compliant.

Global Variable Names

Global variables and singletons begin with an upper case ‘G’. For example, GMyGlobalVariable. The prefix g_ is never used.

Implementation Class Names

Classes that implement methods begin with an upper case ‘C’. For example, CMyClass. A fully qualified method of CMyClass could be MyNamespace::CMyClass::myMethod

Pure Virtual Base Class Names

Such base classes begin with an upper case ‘I’. For example,IMyInterface.

Template Class Names

Template classes begin with an upper case ‘T’. For example,TMyTemplate.

``typedef``’d Type Names

Currently all such types also begin with an upper case ‘T’. That probably needs some resolution to distinguish for template names. The suffix _t is never used.

Structure Names

Structures begin with an upper case ‘S’. For example,SMyStructure. The suffix _s is never used.

Enumerations Names

Enumerations begin with an upper case ‘E’. For example,EMyEnumeration. The suffix _e is never used.

Using Pre-Commit

You can use the pre-commit tool to check for style issues automatically. This is a 3rd party, Python based tool that simplifies linter checks and runs automatically when you commit modifications.

The tool uses the .pre-commit-config.yaml file on the root NuttX directory as reference.

Installing

Follow the installation guide on pre-commitwebsite. If you can’t install directly with pip, consider usingsnap or apt. Then, enter the NuttX repository and run: pre-commit install.

Using

When committing changes, the tool should run automatically. Each check should show “Passed”, otherwise the commit will not happen. If any test fails, you should: fix the errors, then git add and git commitagain.

Example terminal output:

user@machine:~/nuttxspace/nuttx$ git commit -m "Testing pre-commit" fix end of files.........................................................Passed trim trailing whitespace.................................................Passed check for added large files..............................................Passed nxstyle..................................................................Passed [feature/example_wifi 8394e9f3cf] Testing pre-commit 1 file changed, 1 insertion(+)

It is possible to manually run the tool without a commit, just checking all files in a directory. Simply run: pre-commit run --files drivers/i2c/*

Hooks

The following hooks are enabled in .pre-commit-config.yaml:

Appendix

C Source File Structure

/****************************************************************************

/****************************************************************************

All header files are included here.

/****************************************************************************

All C pre-processor macros are defined here.

/****************************************************************************

Any types, enumerations, structures or unions used by the file are defined here.

/****************************************************************************

Prototypes of all static functions in the file are provided here.

/****************************************************************************

All static data definitions appear here.

/****************************************************************************

All data definitions with global scope appear here.

/****************************************************************************

/****************************************************************************

All static functions in the file are defined in this grouping. Each is preceded by a function header similar to the above.

/****************************************************************************

/****************************************************************************

All global functions in the file are defined here.