C-Macro in if-Condition - c

quite a simple problem I have here.
I have a little Macro for a global Variable which is defined in my Header like this:
extern bool uart_message_received;
#define get_uart_message_rec() uart_message_received;
In my C-File I want to access the file like this:
bool uart_message_received = 0;
void foo(void)
{
bool test;
test = get_uart_message_rec(); // Works fine
if(get_uart_message_rec()==0) // Doesn't work
{
//...
}
}
I am a little confused why the condition in the if is not working. Am I doing something wrong, or am I violating some C directives?

#define get_uart_message_rec() uart_message_received
// ^ no semicolon
Macro replacement will substitute the text as is, including the ; in your case. Which will lead to syntax errors in the if case.

Remove the colon at the end of :
#define get_uart_message_rec() uart_message_received;
Because it becomes:
if(**uart_message_received;**==0) // Doesn't work
{
//...
}
When the preprocessor basically does find/replace on your code.

You have a semicolon on the end of your macro - remove that, and it will be fine. Note that macros do replace exactly as written, so your macro expands from:
if(get_uart_message_rec()==0)
to:
if(uart_message_received; ==0)
which should make the compiler error.
[writing too slowly!]

It's because you have a semicolon at the end of the macro.
Macros are replaced as is, before the actual compiler sees the text, so the statement after replacement looks like this:
if(uart_message_received;==0)

Related

How to implement a macro in C

Hi This is legal code for the compiler I use:
#use delay(clock=4M)
now I need to substitute the inside brackets text clock=4M with a macro.
The digit 4 might be any digit, it should be modifiable.
I tried with this
#define CLOCK_SPEED(x) clock=xM
but didnt work.
What you want is the preprocessor concatenation operator, ##.
#define CLOCK(x) clock=x##M
void some_function() {
CLOCK(4);
}
The outcome:
tmp$ cpp -P test.c
void some_function() {
clock=4M;
}
On a side note, macros like these are often the cause of hard-to-find bugs. It is usually recommended to write them like this:
#define CLOCK(x) do { clock=x##M; } while(0)

Reason for always false directive if in C

Here is what I found in an open source project's code:
#if 0
static int print_cb(UNUSED void *ctx, void *i)
{
fprintf(stderr, "%i\n", *(int*)i);
return 0;
}
#endif
Can you explain me what's the reason for this always false if?
Thanks.
It's simply a way to use the preprocessor to comment out (prevent from compiling) a large block of code. It's pretty common.
It's better than using the actual comment syntax since it doesn't nest. If you have:
int foo = 13; /* This won't be needed. */
you can't comment it out by doing:
/*
int foo = 13; /* This won't be needed. */
*/
since the comment syntax doesn't nest, the above will not compile. Using the #if 0 method goes around that limitation.
It is a way of commenting code out. The condition will never be met (0 is never true) so the preprocessor will exclude the code from the compile.
It is typically used on bigger blocks of code that might have some embedded multi-line comments /* */ that cannot be commented out by enclosing them in another multi-line comment.
That is just to disable this code section like Multiline comment. It is better method which avoids nested comments.
From preprocessor definition here
Preprocessor directives are lines included in the code of our programs that are not program statements but directives for the preprocessor. These lines are always preceded by a hash sign (#). The preprocessor is executed before the actual compilation of code begins, therefore the preprocessor digests all these directives before any code is generated by the statements.
So, #if 0 will be decided as #if (false) (losely saying), that means, do not enter the block and skip. A way of commenting out something.

How is this generic function is used

I am going through code where some write has been made to some register. Now they made it as a generic function so that write to different register has to go through the same function:
#define RGS(x) \
static inline void write_##x(u8 val) \
{ \
}
#define REGW(x) RGS(x)
write_wdc(val);
Now I want to know when the call to write_wdc is made, how it is replaced by these macros.
This doesn't show the macro actually being used, in order for the final line (the call) to work, there also has to be something like:
REGW(wdc)
somewhere in the code, to use the macro. The above will be replaced by the preprocessor with:
RGS(wdc)
Which in turn will be replaced with
static inline void write_wdc(u8 val) { }
I assume the body of the function is missing from your macro declaration too, I would expect something like x = val; in there to actually make the write happen.
This uses the ## preprocessor operator to "glue" the words together.

How can I use # in a C preprocessor macro?

I'm trying to use a preprocessor directive in a macro? Can/how can this accomplished?
#define HTTP_REQUEST_RETURN_ERROR(error) *errCode = error;
#ifdef DEBUG
LeaveCriticalSection(&debugOutputLock);
#endif
return NULL
Thanks in advance,
Jori.
You can also, of course, define the macro twice, with different definitions:
#if defined DEBUG
#define HTTP_REQUEST_RETURN_ERROR(error) do { *errCode = error;\
LeaveCriticalSection(&debugOutputLock);\
return NULL;\
} while(0)
#else
#define HTTP_REQUEST_RETURN_ERROR(error) do { *errCode = error;\
return NULL;\
} while(0)
#endif
That makes sure to avoid the (trivially optimizable) run-time if that xdazz used. It also wraps the macro bodies in the typical do ... while, to make it look like a statement.
UPDATE: To clarify, multi-statement macros in C are often wrapped (in the macro definition) in a do ... while(0) loop, since that makes the entire text into a single statement. This lets the usage of the macro work well with scopes and semicolons.
For instance, consider this:
if(httpRequestFailed())
HTTP_REQUEST_RETURN_ERROR(404);
else
processResults();
Without the do ... while(0), the above would be a syntax error since there would be multiple statements between the if and the else. Just adding braces to the macro expansion isn't very clean, since the desirable statement-like usage like the above would result in expansion of
if(httpRequestFailed())
{ ... /* code omitted */ };
which is not very clean, braces following a code scope are not typically followed by a semicolon.
You cannot nest preprocessor directives in a #define.
Define DEBUG and then use the normal if statement.
#define DEBUG 0
#define HTTP_REQUEST_RETURN_ERROR(error) *errCode = error;
if (DEBUG) LeaveCriticalSection(&debugOutputLock);
return NULL

#define, #ifdef #undef #endif

I have the following code
#define PROC_ADD
void main(void)
{
while(1)
{
#ifdef PROC_ADD
// Do this code here then undefined it to run the code in the else
// processing work
#undef PROC_ADD
#else
// now that PROC_ADD has been undefined run this code
// processing work
#endif
}
}
However, it will run the code. But it won't run the code in the else after the PROC_ADD has been undefined.
I think the reason could be that you can only define and undefine at compile time, and not at run-time. However, I am not really sure.
What you are doing is the build time equivalent of:
int x = 1;
int main()
{
if (x)
{
...
x = 0;
}
else
{
...
}
}
ifdef, etc. happen at build time, but for your example, that's not an issue. Once you evaluate the if (either the runtime or build-time form), the decision about which branch to take it made. Changing something after the decision has been made does not change that decision.
The ifdef condition is evaluated when the preprocessor gets to it. When you undef PROC_ADD inside the ifdef'd code, the preprocessor has already decided which section of code to include and which to ignore.
Furthermore, yes: ifdef, undef, etc are processed at pre-processing time -- the compiler never even sees these so-called directives. This of course means run-time code never sees these directives either.
Edit: The preprocessor works by taking a single pass through the text file. The preprocessor does not even care that your text file happens to contain C code! It has zero knowledge that your ifdefs and elses and whatnot happen to be inside a while loop.
#defines only work during preprocessing. So
#define PROC_ADD
void main(void)
{
#ifdef PROC_ADD
// Do this code here then undefined it to run the code in the else
// processing work
#undef PROC_ADD
#else
// now that PROC_ADD has been undefined run this code
// processing work
#endif
}
will be processed the following way: since PROC_ADDR is defined the preprocessor will completely exclude the #else branch and then execute #undef, so the #else branch code never survives preprocessing and never reaches the compiler.
In just about every programming language or syntax, once execution has entered one branch of a conditional (in this case, the conditional being #ifdef, even if the condition changes during execution of the branch, other branches will never be executed.
I'm sure you wouldn't expect this to print "Hello", would you?
if (i == 1)
i = 0;
else
printf("Hello\n");
Basically what you're saying is that the code under the else branch should always execute, then just take it out of a branch, and put it directly in the code.
Both the compiler and the execution only make one pass through conditionals, once a match has been found they look no further.
So you want the code represented by the second comment section to always run? Why not just do
#ifdef PROC_ADD
// Do the stuff to be done if PROC_ADD is defined
#undef PROC_ADD
#endif
// Do the stuff to always be done
edit
OK - if you want run-time behaviour changes you must use run-time constructs (such as a variable to serve as a flag). As we are all saying ;), pre-processor directives are evaluated once only, at compile time.
Think about it this way: else portion of the following code is not executed even though x has been set to false in the if section.
The condition is checked in the if(x) line itself - once it enters that block, it doesn't recalculate each of the subsequent else sections - compiler has already made a decision on that.
bool x = true;
if(x)
{
//do something
x = false;
}
else
{
//else code
}

Resources