istiaq2379 istiaq2379 - 5 months ago 43
C Question

Syntax complication with hash(#) in C programming

In FreeRTOS, it is found an interesting use of hash.

#define osThreadDef(name, thread, priority, instances, stacksz) \
osThreadDef_t os_thread_def_##name = \{ #name, (thread), (priority), (instances), (stacksz) }

I didn't really get the meaning of hash with before name. And there are two hashes and single hash. What does it mean? I searched through internet, but couldn't find anything satisfactory. Thank you.


## and # -- C Macro Operators that Simplify Initializing Memory (as well as being applicable in other creative ways limited only by one's imagination)

## is concatenation and # takes the associated #define macro parameter and substitutes the unquoted parameter input as a null-terminated string (e.g. puts the parameter text in double-quotes "" (see example below). That is very useful in some cases to create powerful macros that can help initialize struct arrays to save typing and make the code more concise and readable.

#define osThreadDef(name, thread, priority, instances, stacksz)  \
osThreadDef_t os_thread_def_##name = \{ #name, (thread), (priority), (instances), (stacksz)  }

Based on that definition we can assume it's written to help initialize a structure whose definition looks something like this:

typedef struct osThreadDef {
   char *threadName;
   thread_t *threadPtr;
   int threadPrio;
   int threadInstanceCnt;
   int stackSize;
} osThreadDef_t;

Example of using the macro in code:

osThreadDef(foobar, &myThr, 5, 10, 100);

That would result in this after pre-processing:

osThreadDef_t os_thread_def_foobar = { 
    "foobar", &myThr, 5, 10, 100 };

In reality, the macro expansion would result in ( ) around the each of last four arguments, but I didn't show that because would just clutter the example. They're added to each parameter in the macro to keep macro-expansion from creating some weird problems in some corner cases, where strange stuff is passed to the macro.

Wrapping macro arguments in ( ) is often done for safety because some kinds of arguments can be problematic. But simple cases like the example don't really require each argument to be wrapped in parenthesis.