I had a look at the code at https://gist.github.com/2728041
May I make some comments?
It contains code which breaks a common C convention.
A macro definition does not follow C syntax. It is a textual replacement, applied to the C source by the 'pre-processor' before the C compiler proper parses the text.
A macro definition is terminated by a 'raw' (not escaped) newline, and not a ';'.
So a macro would normally be defined as, e.g;
#define RD_LOW GPIOC->regs->BRR = RD_bit
or better still:
#define RD_LOW (GPIOC->regs->BRR = RD_bit)
(In C, most things are expressions (not statements), so a macro which is within (...)
is handy because the value can be used as part of any expression, including a parameter to a function, or in a control statement like an if
, for
, while
, switch
.)
Defining a macro with ';' at the end includes the ';' in the source text that the C compiler parses, every place the macro is used. So
#define RD_LOW GPIOC->regs->BRR = RD_bit;
would include the text ';' wherever the name RD_LOW is used.
Summary: As a rule-of-thumb, C programmers don't define macro's (#define ...) with their own ';' statement terminator.
Where practical, macro replacement text is a normal C expression, with (...)
around it (or a single function call).
We use the normal statement terminator ';' after each expression in the body of the C code, where the macro is used.
So macro's don't contain a terminating ';'. An expression-terminating ';' (or separating ',' or other operator) is supplied where the macro is used.
Examples of macro's which have the extra ';'
#define RD_OUTPUT gpio_set_mode(GPIOC, RD, GPIO_OUTPUT_PP );
#define RD_LOW GPIOC->regs->BRR = RD_bit;
Then it is used:
// ....
WR_LOW
WR_HIGH
write8(data&0xff);
WR_LOW
WR_HIGH
Their are a bunch of reasons the terminating ';' is not included in the macro. For example:
a. code does not look like C. It looks like a language which might use new-line as a statement terminator, which is distracting to a C programmer. It causes me to go read the macro's to see why the code looks un-C-like, which isn't necessary.
b. syntax-aware tools might get confused by the lack of ';', and using text search tools like grep, may become awkward.
c. some statements, start to look weird, or become impossible. For example:
for (RD_LOW,i=0; i<10; i++, WR_HIGH)
is a non-starter. Yet, there is no need to constrain the way someone else can write code.
d. it isn't possible to grab the side-effect of a statement and use it's value in a function call, or within an expression.
For example, I might want to:
SerialUSB.print(RD_LOW);
but that won't work.
These are tiny little constraints which are easily avoided by removing the ';' from the macro. When the ';' is removed, the code looks like C, and the macro's can be used in 'normal' expressions as easily as '1'.
I'd recommend removing the ';' from the macro definitions, e.g.:
#define RD_OUTPUT gpio_set_mode(GPIOC, RD, GPIO_OUTPUT_PP)
#define RD_LOW (GPIOC->regs->BRR = RD_bit)
and write the code as:
//...
WR_LOW;
WR_HIGH;
write8(data&0xff);
WR_LOW;
WR_HIGH;
I hope that is helpful.