How to use a global variable in #if conditional check? - c

#define TEST
int i = 1;
int main(int argc, char const *argv[]) {
#if (defined(TEST) && i)
printf("it is printed");
#endif
return 0;
}
Do I have to create another macro for i?

If you want the output if and only if both the macro and the condition on the global variable are true then do like this:
#if (defined(TEST))
if (i)
{ printf("it is printed");
}
#endif
Reason (agreeing with comment by Barmar):
Preprocessor directives are evaluated at compile time, variables are not available at that time.

As in the comments, macro definitions are expanded during the preprocessing stage, before the actual C code compilation.
But why this code compiles and what will be the result of it.
#if (defined(TEST) && i)
preprocessor tests for macro definition TEST. As it was defined, the result of this check is true
now the preprocessor is checking if macro definition (not the C variable!) i exists. As it does not, the whole expression in the #if is evaluated to false.
Generally :
#if a
checks if macro definition a exists and then if its value is != 0,

Related

Cannot resolve function-like macro inside conditional compilation block

Consider the following - I want to check with #if #endif whether a
token is defined somewhere in the code.
I am using a CONCAT(input) macro that should glue the constant and changing parts of the token that I want to check.
Unfortunately, the approach presented below causes a compilation error:
error: missing binary operator before token "("
I have found the expressions that can be put inside a #if #endif block:
https://gcc.gnu.org/onlinedocs/cpp/If.html#If
And apparently it states that:
Macros. All macros in the expression are expanded before actual computation of the expression’s value begins.
It turns out that (CONCAT(test)) should be resolved, but it is not.
Is there any workaround allowing to resolve concatenated token names correctly in a conditional compilation block?
#include <stdio.h>
#define CONCAT(input) string##input
#define stringtest 1
int main(void)
{
#if defined(CONCAT(test)) && (CONCAT(test)==1)
printf("OK");
#else
printf("NOT");
#endif
return 0;
}
If you use just: #if CONCAT(test) == 1 it will work and is enought.
The statement #if defined(CONCAT(test)) does not work because CONCAT(test) will be evaluated to stringtest which will be evaluated to 1, and you can't use defined on a numerical constant.
A different situation came to my mind - what if I want to check whether the token is eg. != 1 Then if it is not defined anywhere, the condition will evaluate to true. So there would be no difference between token not defined and token being different than 1.
You could handle == 0 equal to not defined. So you could use: #if CONCAT(test) != 0 && CONCAT(test) != 1 where CONCAT(test) != 0 means defined(CONCAT(test)). That is the only alternative, because you can't get macro expansion work in a #ifdef or #if defined() statement, see this question which is very similar to yours.
The gcc documentation says:
Conditionals written like this:
#if defined BUFSIZE && BUFSIZE >= 1024
can generally be simplified to just #if BUFSIZE >= 1024, since if BUFSIZE is not defined, it will be interpreted as having the value zero.
Also it can be helpful if you check macro expansion by using gcc -E yourSource.cpp.
gcc --help:
-E Preprocess only; do not compile, assemble or link
You can't do that. Only literals can be used.
You should check for macro directly:
#include <stdio.h>
#define CONCAT(input) string##input
#define stringtest 1
int main(void) {
#if stringtest == 1
printf("OK");
#else
printf("NOT");
#endif
return 0;
}
Since you don't need defined check, you can use like this:
#define CONCAT(input) string##input
#define stringtest 1
int main(void) {
#if CONCAT(test) == 1
printf("OK");
#else
printf("NOT");
#endif
return 0;
}

expected a ")" in IAR IDE

I got the error Error[Pe018]: expected a ")" at CPU_state == cpuStateOff.
When I change cpuStateOff to 0 it's OK. I don't know why.
In my PERIPHERAL_APP.h:
#ifndef __PERIPHERAL_APP_H
#define __PERIPHERAL_APP_H
// CPU state
#define CPU_STATE_OFF 0;
#define CPU_STATE_ON 1;
#endif
In my main.c:
#include "PERIPHERAL_APP.h"
void main( void )
{
initMSP430();
_EINT();
for (;;)
{
if (cpuState == CPU_STATE_OFF ) // The error is hear
{
__bis_SR_register(LPM3_bits);
}
else
{
__bis_SR_register(LPM0_bits);
}
}
}
Preprocessor macros are not C statements, and therefore doesn't need a statement terminator like ;.
What happens is that when the preprocessor replaces the macro cpuStateOff it uses the whole body of the macro, i.e. 0; which results in code like
if (CPU_state == 0; ) // Code after macro replacement
Most compilers and environments have options to stop after preprocessing, if you use it you can see exactly what code the compiler "proper" will see.

How gets an #if Preprocessor conditional which contains a variable resolved without producing an error?

How does an #if Preprocessor stage statement which contain variable of compile time get resolved at preprocessor stage itself?
Below is the code which runs without any error:
#include<stdio.h>
void main()
{
int num=10; /* compile time */
#if((num%2)==0) /* #if is preprocessor stage but has num of compile time why not error here? */
printf("\nNumber is Even");
#else
printf("\nNumber is Odd");
#endif
}
For the evaluation in #if, the preprocessor replaces all identifiers that are already defined macros by their appropriate expansion. All identifiers that remain after that have the value 0.

String comparison in preprocessor conditions in C

I am passing a compiler option in makefile called DPATH, which is something like DPATH=/path/to/somefile. Based on this, I have to write a macro such that:-
#if "$(DPATH)"=="/path/to/x"
#error no x allowed
#endif
How do I compare DPATH with the string in a preprocessor conditional test?
It is not possible to do this in the preprocessor. #if can only evaluate integer expressions making no reference to functions or variables. All identifiers that survive macro expansion are replaced by zeroes, and a string constant triggers an automatic syntax error.
Without knowing more about your problem, I would suggest writing a tiny test program that is compiled and executed during the build, and Makefile goo to fail the build if the test doesn't pass.
#include <stdio.h>
#include <string.h>
int main(void)
{
if (!strcmp(DPATH, "/path/to/x") || some1 == 3 || some2 == 7 || ...)
{
fputs("bogus configuration\n", stderr);
return 1;
}
return 0;
}
and then
all : validate_configuration
validate_configuration: config_validator
if ./config_validator; then touch validate_configuration; else exit 1; fi
config_validator: config_validator.c
# etc

Return with Macro C programming

This code is always returning -1 even when the fopen() function has executed successfully. Is there something I am ignoring.
void nullCheck(FILE* checkVar) {
if(checkVar==NULL) {
#define _NULL_ERROR
}
}
int readFile(char* _name, char* storeArray) {
FILE* fp;
fp=fopen(_name,READ_ONLY_MODE);
nullCheck(fp);
#ifndef _NULL_ERROR
char c=0;
while((c=getc(fp))!=EOF) {
*(storeArray+i)=c;
i+=1;
}
#endif
#ifdef _NULL_ERROR
#undef _NULL_ERROR
return -1;
#endif
return 1;
}
Thanks!
Oy va voy! Macros are defined and undefined when your code is compiled, not when it runs! They are not affected by control flow statements like "if" and "then" -- they are all processed before compilation of those statements even begins!
You need to re-read the documentation on the C Preprocessor. The #define _NULL_ERROR doesn't get executed when nullCheck is called, it gets interpeted when the preprocessor processes the file before it is compiled. So you are always setting _NULL_ERROR and so you will always return -1.
#define is a preprocessor command, which means it's not calculated / processed in the function nullCheck() but before the compiling of the code. so _NULL_ERROR is always defined and therefore the condition
#ifdef _NULL_ERROR
#undef _NULL_ERROR
return -1;
#endif
will always cause the pre-compiler to add the return -1; to your code.
This is what your code looks like to the compiler, after the preprocessor runs:
void nullCheck(FILE* checkVar) {
if(checkVar==NULL) {
}
}
int readFile(char* _name, char* storeArray) {
FILE* fp;
fp=fopen(_name,READ_ONLY_MODE);
nullCheck(fp);
return -1;
return 1;
}
As has been stated above, the preprocessor deals with macros before the compiler runs.
#define, #ifdef, and friends don't work like you think they do. They're preprocessor directives that affect your code even before the compiler sees it. Get your compiler to show you the preprocessed source before it compiles (-E or -save_temps in gcc and clang) and you'll immediately see what's going on.

Resources