svg { background: rgba(255, 255, 255, 0.0); }
image/svg+xml
Zidarics Zoltán
zamek@vili.pmmf.hu
2016
Coding
Embedded
Programming
7.parallel
programming
Compiling to different platforms
different word width
endianness problem
glibc differences
file-name conventions
device access differences
compiler differences
executable binary structure
Different word width
char<short<=int<=long<long long
in 8th bits architecture int is 2 bytes wide,
In 32th bits architecture int is 4 bytes wide,
In 64th bits architecture int can be 8 bytes wide,
if the exact size is important,
uint8_t, int8_t, uint_least8_t, int_least8_t, uint_fast8_t, int_fast8_t
uint16_t, int16_t, uint_least16_t, int_least16_t, uint_fast16_t, int_fast16_t
uint32_t, int32_t, uint_least32_t, int_least32_t, uint_fast32_t, int_fast32_t
uint64_t, int64_t uint_least64_t, int_least64_t, uint_fast64_t, int_fast64_t
(stdint.h)
Endianness poblem
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
0
1 byte széles memória
0xca
0xfe
1
1
1
1
0
0
0
0
1
1
1
1
1
1
1
0
0xca
0xfe
0.
1.
0.
1.
Little Endian
Big Endian
Intel x86-x64 processors
6502 processors
Z80, MCS51 processor family
DEC Alpha, PDP-11, up to ARM 3
Internet
Java programming language
Motorola 68xx processor family
IBM Power, System/360, System 370,
PDP-10, ARM from 4
Jonathan Swift: Gulliver's travels in Lilliput
Addr.
Addr.
Glibc differences
missing objects (mingw)
modules that work differently
complete absence of glibc (embedded systems)
File name conventions
delimiter character (/,\)
disk identifier in Windows
maximum length of file name
accented characters
soft links management
permissions
C coding standard
names
formatting
documenting
layer structure
recommendations
Naming rules
pointer variables
_max() maximum value service
use talking names
end of function names refer to the function
_cnt() the current number of elements of some set
_key() key value service
pl. retry_max() query the maximum value of an object
start of function names
is_ existence test
get_ getting a value
set_ setting a value
pl. is_hit_retry_limit()
module name in the name
uint32_t timeout_msecs;
int ser_is_queue_empty()
int ser_get_next_packet()
function local variable (stack variable)
each letter is lowercase
separating words with _ (underscore)
time_t time_of_error;
* character must be before the variable name
char *name, address;
char* name, address;
global variables
avoid using!
if necessary, start with g_
Logger g_log;
global constants
all letters are uppercase
separating words with _ (underscore)
const int A_GLOBAL_CONSTANT=5;
macro names
all letters of the name are uppercase
separating words with _ (underscore)
if multiline, at the end of the line \
if there are multiple statements, or if there is in the code do {} while (0)
#define MALLOC(ptr,size) \
do { \
ptr=malloc(size); \
if (!ptr) \
abort(); \
while(0)
Do not put ; (semicolon) at the end of the macro!
enum names
all letters in labels are capital letters
separating words with _ (underscore)
enum PinStateType { PIN_OFF, PIN_ON };
Formatting
while
(
1
) {
if
(valid) {
}
/* if (valid) */
else
{
}
/* if (valid) */
}
/* while(1) */
parentheses
the closing member of the parentheses should be commented on
K&R:
if
(condition) {
...
}
ANSI:
if
(condition)
{
...
}
put space after keywords, not after function names
if
(condition) {
}
while
(condition) {
}
strcpy(s, s1);
return
(
1
);
the maximum length of a line is 78 characters
alignment
size of a tab 4-6 byte
use the IDE auto-formatting feature
formatting if then else
if
(condition) {
}
else if
(condition) {
}
else
{
}
formatting a condition
the constant in the expression should always be to the left
if
(
6
==errorNum) ...
formatting switch
documenting case branches is allowed
always have a default branch due to error handling
switch
(...)
{
case
1
:
...
/* comments */
case
2
:
{
int
v;
...
}
break
;
default
:
}
for
(...) {
while
(...) {
...
if
(disaster) {
goto
error;
}
}
}
...
error:
clean up the mess
Using goto
not "from the devil"
Continue & break
in case of incorrect organization, the cycle variable may be crossed
increase / decrease instruction
while
(TRUE) {
...
/* A lot of code */
...
if
(some condition) {
continue
;
}
...
/* A lot of code */
...
if
( i++ > STOP_VALUE)
break
;
}
mixed use of continue and break in one cycle
sure recipe for chaos
Elvis operator
(condition) ? func1() : func2();
(condition)
? long statement
: another long statement;
Only one statement per line
char **a, *x;
// not recommended
char
**a=0;
// add doc
char
*x=0;
// add doc
Use inline functions instead of macros
the compiler does not compile the code that the programmer sees (macro preprocessor)
#define MAX(x,y) ((x)>(y) ? (x) : (y)) // not recommended
inline int
max(int x, int y) {
return
(x>y ? x : y);
}
Initialize all variables
the gcc -W switch reveals uninitialized variables,
but rather go for sure
Write short functions
a function should have a maximum of one screen (max. 20 lines)
break down the code of longer functions into subtasks
implementation functions
while
(*dest++ = *src++)
;
Indicate the null statement
Documentation
use Doxygen to document the code
avoid comment poisoning
int
some_func(
int
from,
int
to) {
int
temp=from;
// local variable initialized with from
for
(;
// for cycle there is no need init, because it initialized
temp<to;
// do it until temp less than to
++temp)
// increment temp at every cycle step
printf("temp:%d",temp);
// print the current value of temp
return
EXIT_SUCCESS;
// return with EXIT_SUCCESS
}
Fill in each module
\author
author of the module
\version
version of the module
\param
arguments of the function
\return
return value of the function
\deprecated
denote deprecated function
\see
link for a more complete understanding of the documented object
\todo
administering unresolved issues
\bug
administer errors caused by the function
Layer structure
best way to reduce the complexity of a system
break down the task into functional layers
each layer communicates only with adjacent layers
through predefined interfaces
communication between non-adjacent layers is prohibited
serial port character
serial packet
serial driver
start_measurement(),
get_measured_data(),
stop_measurement(),
set_measurement_params()
send_packet()
is_queue_empty()
get_next_packet()
free_packet()
send_buffer()
is_next_character()
read_buffer()
Recommendations
do not use floating point variables if you need discrete values
floating point cycle variable is the best method for suicide
never try to compare floating point variables with the ==,! = operator,
only <= or >= can be used
avoid giving value in the condition
if (abool=bbool)
abool=bbool;
if (abool)
modern compilers automatically store local variables in a cpu register if possible
use the #if macro instead of #ifdef
#ifdef DEBUG
temporary_debugger_break();
#endif
if someone calls the translator like this:
cc -c main.c -DDEBUG=0
#if DEBUG
temporary_debugger_break();
#endif
if you really need ifdef
#if !defined(USER_NAME)
#define USER_NAME "Zaphod Beeblebrox"
#endif
there should be no data definition in the header files
if you really need it, have the definition in the .c file and reference it with extern
/**
\file amodule.c
*/
int
x=
0
;
/**
\file bmodule.c
*/
extern int
x;
there should be no magic number constants in the code
/**
\file amodule.h
*/
int
x=
0
;
if
(
22
== foo)
start_thermo_nuclear_war();
else if
(
19
== foo)
refund_lotso_money();
else if
(
16
== foo) infinite_loop();
else
cry_cause_im_lost();
#define PRESIDENT_WENT_CRAZY (
22
)
const int
WE_GOOFED=
19
;
enum
{
THEY_DIDNT_PAY=
16
};
if
(PRESIDENT_WENT_CRAZY == foo)
start_thermo_nuclear_war();
else if
(WE_GOOFED == foo)
refund_lotso_money();
else if
(THEY_DIDNT_PAY == foo)
infinite_loop();
else
happy_days_i_know_why_im_here();
Creating a module for C++
#ifndef _MODUL_INCLUDE_
#define _MODUL_INCLUDE_
#ifdef __cplusplus
namespace
tr_control {
extern
"C" {
#endif // __cplusplus
int
ma_init();
int
ma_close();
#ifdef __cplusplus
}
}
using namespace
tr_control;
#endif // __cplusplus
#endif // _MODUL_INCLUDE_
/*
Copyright (C) year your name.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled ``GNU
Free Documentation License''.
*/
GPL license
if you release the code under a GPL license, all files
have the GPL header at the beginning:
Documentation
C kódolási szabvány
GNU Coding Standards
Make a flowchart
Pizzeria bake
Pizzeria bake
No
No
Make a pizza
Make a pizza
Yes
Yes
No
No
Queue full?
Queue full?
lock mutex
lock mutex
insert pizza to queue
insert to queue
queue
unlock mutex
unlock mutex
sleep
sleep
Exit
Exit
Pizzeria consume
Pizzeria consume
Yes
Yes
Is kitchen opened?
kitchen opened?
Kitchen open
wait
Kitchen open_wai
No
No
Yes
Yes
is queue
empty?
queue_empty?
Yes
Yes
Is guests
<
GUEST_MAX?
guest<GUEST_MAX?
lock mutex
lock mutex
remove pizza
from queue
remove
unlock mutex
unlock mutex
Exit
Exit
No
No
No
No
Is kitchen opened?
kitchen opened?
dia
draw.io
Creating library
frequently used codes do not need to be recompiled
static library
shared library
P3_LibDemo
Static library
the code in a precompiled binary (.a)
the compiler adds this in the linking phase
for binary
advantages
there is no need to recompile the library code
no library source code required
disadvantages
the executable binary contains the library, easier portability
the size of the executable binary increases with the size of the library
if the library code changes, all applications that use it
must be translated again
compiling
first phase is the same as normal code compilation
instead of linking phase:
ar rcs <library_filenév> <obj_file_list>
result: lib<library_name>.a
reference from other projects
in linking phase:
gcc -o <bin_filename> [-L <library_path>] -l <lib_filename> -o <obj_files>
pl.: ar rcs libserial.a serial_low.o serial_packet.o serial_app.o
result: libserial.a
pl.: gcc -o measurement -L ../serial/lib -lserial -o meas.o processing.o
Shared library
the code is a precompiled binary file of the operating system
directory (/ lib, / usr / lib, / usr / local / lib)
the compiler only checks the existence of the library in the editing phase
advantages
there is no need to recompile the library code
no library source code required
disadvantages
the library exists in only one instance
ensuring portability is more difficult because you need to check the existence and version number of the library
compiling
first phase:
gcc -c -fPIC <source_name.c> -o <object_name>
linking phase:
gcc -shared -Wl,-soname,<library_name>.so -o <library_name>.so <object_file_name> -lc
result: lib<library_name>.so
hivatkozás más projektekből
a szerkesztési fázisban:
gcc -o <bin_filename> [-L <library_path>] -l <lib_filename> -o <obj_files>
pl.: gcc -c -fPIC src/char_queue.c -o obj/char_queue.o -Wall -pedantic
gcc -shared -Wl,-soname,libcharqueue.so -o obj/libcharqueue.so obj/char_queue.o -lc
result: libcharqueue.so
pl.: gcc -L ../obj -Wall -pedantic -o obj/test -l charqueue -lcmocka -lpthread obj/test.o
if the library code is modified but the functions call interface is not, then
individual projects do not need to be recompiled
9.Regex
1
Main
Compiling to different platforms
Different word with
Endianness problem
Glibc differences
File name conventions
C coding standard
Naming rules I.
Naming rules II.
Naming rules III.
Formatting I.
Formatting II.
Formatting III.
Using goto
Continue & break
Elvis operátor
Only one statement per line
Use inline functions instead of macros
Initialize all variables
Write short functions
Indicate the null statement
Documentation
Fill in each module
Layer structure
Recommendation I.
Recommendation II.
Recommendation III.
Recommendation IV.
Recommendation V.
GPL license
Make flowchart
Flowchart maker software
Documentation
Creating library
Static library
Shared library
next