\n
). (How to handle line endings in
Git: https://help.github.com/articles/dealing-with-line-endings)/dist/tools/whitespacecheck/check.sh master || exit
can be
used to detect whitespaces at the end of line(s) that would lead to
Murdock build error(s).while (HW_STATUS != STATUS_OK) {}
is correct,
while (HW_STATUS != STATUS_OK);
is wrong.typedef
s is
completely different
(see below) (BTW: Do we have any reason to do so?)IS_ACTIVE
and IS_USED
macros from kernel_defines.h
with C
conditionals. If a symbol is not going to be defined under a certain
condition, the usage of preprocessor #if defined()
is fine.Using extensions to the C standard in general decreases portability and maintainability: The former because porting RIOT to platforms for which limited compiler options are available becomes more difficult when compiler-specific extensions are used. The latter because extensions are often not as clearly defined as standard C, not as well known within the C development community, and have fewer resources to look up.
There are a number of cases in which using extensions cannot be avoided, or would not be maintainable. For these cases, an exception can be made. A list of recognised exceptions where we can (or even must) rely on extensions include:
__attribute__((packed))
is allowed for serialization and
de-serialization and only there. Ideally, it should not be used in public
APIs and types.#include_next
may be used when system headers need to be extended.compiler_hints.h
may be
used using that wrapper. These wrappers either unlock additional optimization
(such as NORETURN
or PURE
) or influence warnings (such as MAYBE_UNUSED
)
produced by the compiler and can simply be replaced by an empty token for
compilers that do not support them.__attribute__((used))
, __attribute__((section("...")))
,
__attribute__((weak))
, and __attribute__((alias("...")))
can be used where applicable. Unlike the wrappers in compiler_hints.h
, we
actually require toolchain support for them (an empty-token implementation
will not generate correct binaries).int
or long
. Use data
types that include the bit length in the name like uint16_t
when you need to
make sure that a certain variable is exactly of this length.typedef
) always end on "_t". typedef struct {
uint8_t a;
uint8_t b;
} foobar_t;
typedef struct mystruct mystruct_t;
[...]
struct mystruct {
[...]
};
char *
for strings and only for stringsuint8_t[]
as type for arbitrary byte buffers, but use void *
to
pass them around. uint8_t[]
because we're dealing with bytes and not
characters, void *
to avoid unnecessary casting shall the need arise to
have their content to have a certain typeuint8_t *
to pass "typed" byte buffers, e.g., link-layer addresses,
where it avoids unnecessary temporary variablevoid *
for generic typingextern
.(void)
.NULL
indicates an error case, too. thread_getpid(void);
hwtimer_init_comp(uint32_t fcpu);
int transceiver_pid;
/* instead of: */
void CamelCaseNamedFunction(int camelCaseNamedVar);
/* write: */
void camel_case_named_function(int camel_case_named_var);
while
in a
do
-statement, it goes into the same line. /* instead of: */
if (debug) println("DEBUG");
else println("DEBUG ELSE");
/* write: */
if (debug) {
println("DEBUG");
}
else {
println("DEBUG ELSE");
}
Add two spaces of indent after the #
per level of indent. Increment the
indent when entering conditional compilation using #if
/#ifdef
/#ifndef
(except for the include guard, which does not add to the indent). Treat indent
for C language statements and C preprocessor directives independently.
/* BAD: */
#if XOSC1
#define XOSC XOSC1
#define XOSC_NUM 1
#elif XOSC2
#define XOSC XSOC2
#define XOSC_NUM 2
#endif /* XOSC1/XOSC2 */
/* GOOD: */
#if XOSC1
# define XOSC XOSC1
# define XOSC_NUM 1
#elif XOSC2
# define XOSC XSOC2
# define XOSC_NUM 2
#endif
/* BAD: */
void init_foo(uint32_t param)
{
(void)param;
#if HAS_FOO
switch (param) {
case CASE1:
do_foo_init_for_case1;
break;
#if HAS_CASE_2
case CASE2:
do_foo_init_for_case2;
break;
#endif
#endif
}
/* GOOD: */
void init_foo(uint32_t param)
{
(void)param;
#if HAS_FOO
switch (param) {
case CASE1:
do_foo_init_for_case1;
break;
# if HAS_CASE_2
case CASE2:
do_foo_init_for_case2;
break;
# endif
#endif
}
Adding the indent does improve readability a lot, more than adding comments. Hence, we prefer the indent to allow reviewers to quickly grasp the structure of the code.
Adding spaces before the #
is not in compliance with the C standard (even
though in practice compilers will be just fine with whitespace in front), but
adding spaces afterwards is standard compliant. In either case, having the #
at the beginning of the line makes it visually stand out from C statements,
which eases reading the code.
Using an indent width of 2 makes preprocessor directives visually more distinctive from C code, which helps to quickly understand the structure of code.
#ifdef MODULE_...
statement around includes of optional headers:#ifdef MODULE_ABC
# include "abc.h"
#endif
#include
directives that are not actually needed should be removed to reduce
clutter and improve compilation speed. Similar: Try to add the corresponding
#include
s for all the functions, macros, types, etc. used and do not rely on
bar.h
to implicitly include foo.h
, unless this is documented behavior.
Tools such as clang's Include Cleaner can help with
that. These tools may show false positives in cases where headers are expected
to be included indirectly: E.g. if foo.h
is the public header that contains
common helpers and implementations, but a per platform foo_arch.h
is included
from within foo.h
for platform specific implementations. If in this scenario
only functions provided by foo_arch.h
are included, the #include
of foo.h
is considered as unused. To avoid this, one should add
/* IWYU pragma: export */
after #include "foo_arch.h"
in foo.h
.
All header files are required to either contain the widely supported #pragma once
preprocessor directive as the first line after the copyright note,
or header guards of the form
#ifndef PATH_TO_FILE_FILENAME_H
#define PATH_TO_FILE_FILENAME_H
...
#endif /* PATH_TO_FILE_FILENAME_H */
Header guards are deprecated in RIOT header files and will gradually be converted
to #pragma once
.
Rules for generating the guard name:
include/
in the file's pathname, include the path from there
on.Examples:
Note: these rules will be enforced by the CI.
extern "C"
#ifdef __cplusplus
extern "C" {
#endif
... all your function declarations, global variables and defines belong here
#ifdef __cplusplus
}
#endif
__restrict
instead of restrict
in headers (compare
https://github.com/RIOT-OS/RIOT/pull/2042)int timeout = 7 * 1000000;
write
int timeout = TIMEOUT_INTERVAL * USEC_PER_SEC;
E.g:
/* This is a C-style comment */
Wrong:
// C++ comment here
An exemplary doxygen documentation in a header file can look like this.
/*
* Copyright (C) 2014 Peter Schmerzl <peter@schmerzl-os.org>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup foobar
* @{
*
* @file
* @brief Definitions for foo and bar functions.
*
* More detailed information about the file and the functionality implemented.
*
* @author Peter Schmerzl <peter@schmerzl-os.org>
*
*/
/**
* @brief Set the state of foobar.
*
* @param[in] state The new state of foobar.
* @param[out] old_state The old state of foobar is written to this variable.
*
* @return 1 if setting the state was successful, 0 otherwise.
*/
int set_foobar(int state, int *old_state);
Some solutions to correctly handle compilation warnings.
Solution for string formatting errors:
size_t
PRIuSIZE
from architecture.h
because newlib-nano
does not support %zu
unsigned char/uint8_t
%u
because newlib-nano
does not support %hu/PRIu8
example
uint32_t
PRIu32
print format
example
64bit
variables
For a printf
style function with the following error: error: format string is not a string literal
.
__attribute__((__format__ (__printf__, 3, 4)))
, where here 3
is
the number of the argument with the format and 4
the format arguments,
starting from 1. See
example
va_list
:
__attribute__((__format__ (__printf__, 1, 0)))
, where here 1
is
the number of the argument with the format and 0
as there is no variable
numbers of arguments. See
example
/* cppcheck-suppress <category of error/warning>
* (reason: cppcheck is being really silly. this is certainly not a
* null-pointer dereference */
#!/usr/bin/env python3
#!/usr/bin/env python3
# Copyright (C) <your copyright>
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
# put the module imports first
# see https://www.python.org/dev/peps/pep-0008/#imports
# for more details
import module1
import module2
# Optional global variables
GLOBAL_VARIABLE = "I'm global"
# local functions, if required
def local_func():
# Put your local function code here
# The main function
def main_func():
# Put your main code here
if __name__ == "__main__":
# Call the main function from here:
main_func()
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )