# Compile time calculations in C

I have been implementing a control software in C programming language. One of the software modules represents a communication table for some proprietary communication protocol. Each record in this table has one item (among others) consisting of 8 bits. This item represents properties associated to this record. Each record can has below given properties:

reported, event_logged, time_logged, archived, global

I need to define the communication table and for sake of readibility I don't want to fill the properties of each record with values 0-31. My idea was to at first define below given bit masks for individual bits in the properties byte:

#define REPORTED       0x10
#define EVENT_LOGGED   0x08
#define TIME_LOGGED    0x04
#define ARCHIVED       0x02
#define GLOBAL         0x01


Then I wanted to define a macro with parameters which will prepare the content of the properties based on human readable values

#define Create_properties(reported, event_logged, time_logged, archived, global){ \
(uint8_t)reported | (uint8_t)event_logged | (uint8_t)time_logged |              \
(uint8_t)global                                                                 \
}


The planned usage is following. For example one of the records in the communication table will be event logged and time logged so I will write the macro in this manner

Create_properties(0, EVENT_LOGGED, TIME_LOGGED, 0, 0, 0)


and the expected result is 01100. I have been facing a problem that I am not able to compile this source code. I always receive compiler error "braces around scalar initializer". I have been using the gcc compiler. Does anybody know why does this error occur? Thanks for any ideas.

• In general, I would advise to ask pure programming questions like this on stackoverflow.com. Your question is on-topic here & just fine, but you'll get far better quality if you ask this to C gurus at SO. – Lundin Oct 22 '18 at 14:32
• I'm voting to close this question as off-topic because this is pure programming, and best suited to a different exchange. – Scott Seidman Oct 22 '18 at 15:03
• @Lundin Your comment proves that at least one of those C gurus have a presence at "our" site as well. ;) – pipe Oct 22 '18 at 15:18

Curly braces {} are not used for macro definitions. Try removing them and see if it works:

#define Create_properties(reported, event_logged, time_logged, archived, global) \
(uint8_t)reported | (uint8_t)event_logged | (uint8_t)time_logged |              \
(uint8_t)global

• It works without curly brackets. Thank you, Justin. – Steve Oct 22 '18 at 14:05
• @Steve Then be sure to select the answer (the check button) so that future searches will reveal an answered question. – a concerned citizen Oct 22 '18 at 14:10
• This is a dangerously-written macro. As a bare minimum, you need to surround it with parenthesis. The casts are superfluous and can be removed, or you can cast the end result to the intended type. – Lundin Oct 22 '18 at 14:29

Since these are only 8 bit numbers, you could safely use an enum. Pick some code prefix that makes sense - I don't know what your code is supposed to do so I used STUFF_ as place-holder, to be replaced by a better name.

enum
{
STUFF_REPORTED     = 0x10,
STUFF_EVENT_LOGGED = 0x08,
STUFF_TIME_LOGGED  = 0x04,
STUFF_ARCHIVED     = 0x02,
STUFF_GLOBAL       = 0x01,
};


Then simply create a macro for each case:

#define STUFF_EVENT_TIME_LOGGED ( (uint8_t)(STUFF_EVENT_LOGGED | STUFF_TIME_LOGGED) )


Making a function-like macro such as Create_properties gives no benefit, since it might be confused for a function and will have zero type-safety, making it hard to read and dangerous both. So I wouldn't recommended it, function-like macros should be avoided if possible. But of course it can be done too:

#define Create_properties(reported, event_logged, time_logged, archived, global) \
(uint8_t) ((reported) | (event_logged) | (time_logged) | (archived) | (global))


Notably, your casts to uint8_t were completely pointless, because each operand of | will get integer promoted to int anyway. If you should cast to something before the | takes place, it would need to be uint32_. Or you can just cast to uint8_t after the operation, as in my macro above.