How to use conditional #error - c

I have a an application header file in c where I mention the variable.
#VAR_X "testData"
User can change this variable but I want to restrict it's length to maximum of 50.If user tries to make it more than 50 there should be an error on building the code.
I have done like this in the application.h:
#define __IS_MORE if((strlen(VAR_X) - 50) > 0) 1:0;
and in application.c at the top .
#define application.h
#if defined(__IS_MORE)
#error "Size is more than the maximum size"
#endif
But no matter what I put in the VAR I always get the #error directive "Size is more than the maximum size"
What wrong I am doing?

At compile time, you can do this by using a technique called as static assert. you can find the details here. Assuming a STATIC_ASSERT macro is defined as explained in the link, you can do the following to check if VAR_X exceeds the length (Here I assume that VAR_X is a macro as in #define VAR_X "...")
STATIC_ASSERT(sizeof(VAR_X) <= 50, "Size of VAR_X is more than the maximum size");
Some example code
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
#define VAR_X "012345678912912"
STATIC_ASSERT(sizeof(VAR_X) <= 50, Size_of_VAR_X_is_more_than_the_maximum_size);
int main()
{
return 0;
}

#define and #if are part of the C preprocessor and are evaluated before compiling the code.
The line #if defined(__IS_MORE) simply evaluates if the label __IS_MORE has been defined, which it has. Therefore the #error is processed.
What you are wanting to do (make sure that programmer can't define VAR_X with more than 50 characters) can not be done at the preprocessor level. The best you can do is put a run time check at the start of the code if you need to.

#ifdef (and #if defined(..)) are precompiler checks and are true if the symbol is defined at the point the code is compiled.
It doesn't matter WHAT you define #define __IS_MORE as, the macro IS defined as something, hence the error.
As your check requires evaluation of strlen at run time, you could look instead at a construct like assert to enforce your check.

Related

Unusual syntax for a #define directive

In a sketch I found the following instruction:
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
And I want to be sure not to make any mistake: why are there two "mA"?
Which one should I replace by a value given that in a previous version of this code one just needed this line:
#define USB_CONFIG_POWER_MA(20)
to set the max to 20mA but now it gives a compilation error:
/home/henry/arduino-1.8.16/hardware/arduino/avr/cores/arduino/USBCore.h:99:29: error: "20" may not appear in macro parameter list
This seems to be the solution as it gives me no compilation error
#define USB_CONFIG_POWER_MA(mA) ((40)/2)
but again i want to be sure!
With
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
you define a function-like macro, where mA is the argument to the macro.
You can use it like:
printf("USB power for 20 mA is %d\n", USB_CONFIG_POWER_MA(20));
The preprocessor will replace the macro as such:
printf("USB power for 20 mA is %d\n", ((20)/2));
If you always want the macro to be replaced by the value 20 then either define a function-like macro where you ignore the argument (this will be backward compatible):
#define USB_CONFIG_POWER_MA(mA) 20
Or define a macro without arguments (this will require you to change all macro invocations):
#define USB_CONFIG_POWER_MA 20
The latter, without arguments, is often used in C as a way to define symbolic constants, and as such makes more sense in your use-case.
Another possible solution is to use the original macro definition, but use a second macro to define the value to pass as argument:
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
#define USB_CONFIG_DEFAULT_POWER 40
// ...
printf("USB power for 20 mA is %d\n",
USB_CONFIG_POWER_MA(USB_CONFIG_DEFAULT_POWER));
This will both be backward compatible and allow other values to be used together with the original USB_CONFIG_POWER_MA macro.
to set the max to 20mA
You shouldn't change the definition of the USB_CONFIG_POWER_MA macro, you should change the value that's passed to it where it's used. The macro you're talking about comes from USBCore.h:
#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, \
USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, \
USB_CONFIG_POWER_MA(USB_CONFIG_POWER) }
You can see the macro being used to set the configured power here. Looking deeper, the definition of USB_CONFIG_POWER is:
#ifndef USB_CONFIG_POWER
#define USB_CONFIG_POWER (500)
#endif
So USB_CONFIG_POWER only gets defined if it isn't already defined. That means that all you need to do to set the power that your Arduino sketch requests is to make sure that you define USB_CONFIG_POWER yourself before you include the USBCore.h file. Put a line like:
#define USB_CONFIG_POWER (20)
in your code before you include that file, and you should be good to go.

Preprocessor directives in C : macros using __LINE__

I find it difficult to understand the working of a macro defined with the help of preprocessor directives.
The macro,
TRXEM_SPI_BEGIN()
is defined with the help of two preprocessor directives refereed from two header files. Firstly, I wish to state the declaration of the said macro.
#define TRXEM_SPI_BEGIN() st( TRXEM_PORT_OUT &= ~TRXEM_SPI_SC_N_PIN; NOP();)
As the declaration of macro st () is missing here, I found it defined in a different header file and ti is shown below.
#define st(x) do { x } while (__LINE__ == -1)
Now after combining two macros, the true definition of macro TRXEM_SPI_BEGIN() must be,
#define TRXEM_SPI_BEGIN() do {
( TRXEM_PORT_OUT &= ~TRXEM_SPI_SC_N_PIN; NOP(); )
} while (__LINE__ == -1)
This code is written to work inside a microcontroler where TRXEM_PORT_OUT, RXEM_SPI_SC_N_PIN are memory mapped registers and NOP initiates an instruction cycle that does nothing.
As per my understanding, __LINE__ means the line of code in the c file where __LINE__ lies. That line can never be equal to -1. i.e. this loopmust always be running only once provided the __LINE__ can never be placed in -1 place in a .c file. Simply put, -1 can never be the value of __LINE__.
Therefore, I believe a do while() loop here is unnecessary and the same output could have been achieved by simply without using any looping.
I do not understand the functioning of this macro. I would so much appreciate if someone could elaborate on it.
As per my understanding, means the line of code in the c file
where __LINE__ lies. That line can never be equal to -1. i.e. this
loopmust always be running only once provided the __LINE__ can never
be placed in -1 place in a .c file. Simply put, -1 can never be the
return value to a __LINE__.
Your understanding is exactly correct here. It is there to make sure the code runs exactly once.
Think of following scenario:
#define BAZ foo();bar();
Now if you do
if(some_cond) BAZ;
This is equivalent to:
if(some_cond) foo();
bar();
Which is most possibly not something you want. So you change it to:
#define BAZ {foo();bar();}
This works fine if written as if(some_cond) foo() else wow(); but would fail compilation if written as if(some_cond) foo(); else wow();
So you define BAZ as
/* No semicolon at end */
#define BAZ do {foo();bar();} while(condition_which_is_always_false)
And you can now write the natural code with intuitive semicolon at end.
In your case, condition_which_is_always_false is __LINE__ == -1

Is there a way to both check a macro is defined and it equals a certain value at the same time

I regularly use object-like preprocessor macros as boolean flags in C code to turn on and off sections of code.
For example
#define DEBUG_PRINT 1
And then use it like
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
However, it comes a problem if the header file that contains the #define is forgotten to be included in the source code. Since the macro is not declared, the preprocessor treats it as if it equals 0, and the #if statement never runs.
When the header file is forgotten to be included, non-expected, unruly behaviour can occur.
Ideally, I would like to be able to both check that a macro is defined, and check that it equals a certain value, in one line. If it is not defined, the preprocessor throws an error (or warning).
I'm looking for something along the lines of:
#if-def-and-true-else-throw-error(DEBUG_PRINT)
...
#endif
It's like a combination of #ifdef and #if, and if it doesn't exist, uses #error.
I have explored a few avenues, however, preprocessor directives can't be used inside a #define block, and as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
This may not work for the general case (I don't think there's a general solution to what you're asking for), but for your specific example you might consider changing this sequence of code:
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
to:
if (DEBUG_PRINT == 1) {
printf("%s", "Testing");
}
It's no more verbose and will fail to compile if DEBUG_PRINT is not defined or if it's defined to be something that cannot be compared with 1.
as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
It can't be an error because the C standard specifies that behavior is legal. From section 6.10.1/3 of ISO C99 standard:
After all replacements due to macro expansion and the defined unary
operator have been performed, all remaining identifiers are replaced with the pp-number
0....
As Jim Balter notes in the comment below, though, some compilers (such as gcc) can issue warnings about it. However, since the behavior of substituting 0 for unrecognized preprocessor tokens is legal (and in many cases desirable), I'd expect that enabling such warnings in practice would generate a significant amount of noise.
There's no way to do exactly what you want. If you want to generate a compilation failure if the macro is not defined, you'll have to do it explicitly
#if !defined DEBUG_PRINT
#error DEBUG_PRINT is not defined.
#endif
for each source file that cares. Alternatively, you could convert your macro to a function-like macro and avoid using #if. For example, you could define a DEBUG_PRINT macro that expands to a printf call for debug builds but expands to nothing for non-debug builds. Any file that neglects to include the header defining the macro then would fail to compile.
Edit:
Regarding desirability, I have seen numerous times where code uses:
#if ENABLE_SOME_CODE
...
#endif
instead of:
#ifdef ENABLE_SOME_CODE
...
#endif
so that #define ENABLE_SOME_CODE 0 disables the code rather than enables it.
Rather than using DEBUG_PRINT directly in your source files, put this in the header file:
#if !defined(DEBUG_PRINT)
#error DEBUG_PRINT is not defined
#endif
#if DEBUG_PRINT
#define PrintDebug([args]) [definition]
#else
#define PrintDebug
#endif
Any source file that uses PrintDebug but doesn't include the header file will fail to compile.
If you need other code than calls to PrintDebug to be compiled based on DEBUG_PRINT, consider using Michael Burr's suggestion of using plain if rather than #if (yes, the optimizer will not generate code within a false constant test).
Edit:
And you can generalize PrintDebug above to include or exclude arbitrary code as long as you don't have commas that look like macro arguments:
#if !defined(IF_DEBUG)
#error IF_DEBUG is not defined
#endif
#if IF_DEBUG
#define IfDebug(code) code
#else
#define IfDebug(code)
#endif
Then you can write stuff like
IfDebug(int count1;) // IfDebug(int count1, count2;) won't work
IfDebug(int count2;)
...
IfDebug(count1++; count2++;)
Yes you can check both:
#if defined DEBUG && DEBUG == 1
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
In this example even when #define DEBUG 0 but it is not equal to 1 thus nothing will be printed.
You can do even this:
#if defined DEBUG && DEBUG
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
Here if you #define DEBUG 0 and then D(1,2,3) also nothing will be printed
DOC
Simply create a macro DEBUG_PRINT that does the actual printing:
#define DEBUG_PRINT(n, str) \
\
if(n == 1) \
{ \
printf("%s", str); \
} \
else if(n == 2) \
{ \
do_something_else(); \
} \
\
#endif
#include <stdio.h>
int main()
{
DEBUG_PRINT(1, "testing");
}
If the macro isn't defined, then you will get a compiler error because the symbol is not recognized.
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif
So when "if 0" it'll do nothing and when "if 1" it'll execute the defined macro.

Call from c code a kernel variable in freebsd

I found some online resources about this topic but still can not understand how it works.
Lets assume that I have a global variable with following specification
in file: /sys/sys/sysctl.h
#define USER_TZNAME_MAX 20 /*test var*/
and in file /usr/src/sys/kern/kern_mib.c a
SYSCTL_INT(_user, USER_TZNAME_MAX, tzname_max, CTLFLAG_RW, 0, 0, "something");
can anyone show practically how to change the variable value and set another value in a c source file?
Thank you
#define USER_TZNAME_MAX is not defining a global variable, it is a preprocessor macro.
Before the compiler compiles the code the preprocessor is run to expand macros and include/exclude code as defined by definitions.
In an example such as this, the preprocessor will replace all instances of the string "USER_TZNAME_MAX" in the source with the string "20":
// this
int i = USER_TZNAME_MAX;
// will be expanded to this:
int i = 20;
Therefore you can't change this variable at run time because a) it isn't a variable, and b) it's a constant.
If you're talking about changing the value used in your own code you can do this:
#ifdef USER_TZNAME_MAX
#undef USER_TZNAME_MAX
#endif
#define USER_TZNAME_MAX (32)
In programs, you should use sysctl(3) to get or set system information.

#define LOG_MSG(...) for debugging

How does the following code work?
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_MSG printf
#else
#define LOG_MSG(...)
#endif
Depending on the value of ENABLE_DEBUG, LOG_MSG is either defined to be an alias for printf() or it is defined as a no-op macro. It is implied that you can change the value to 0 to disable debugging. This is a common technique for making it easy to switch between debugging builds which display lots of output and release builds which are quiet.
#define LOG_MSG printf
This makes it an alias for printf().
#define LOG_MSG(...) /* empty */
And this defines it as an empty macro. Notice that here it has a set of parentheses, which means the macro takes parameters. It has nothing afterwards which means it expands to absolutely nothing. And the ... indicates that this macro can take a varying number of arguments. This syntax is a C99 extension so it may not be available on older C compilers.
LOG_MSG("file not found\n");
The result is that a LOG_MSG() call will either print a message or do nothing depending on whether logging is enabled.
// If ENABLE_DEBUG is non-zero, a debugging printout:
printf("file not found\n");
// If ENABLE_DEBUG is zero, an empty statement:
;
For what it's worth, whoever authored this macro could've done a better job by replacing the first definition with one using the ... syntax (which he/she is clearly familiar with), printing to stderr instead of stdout:
#define LOG_MSG(...) fprintf(stderr, __VA_ARGS__)
This uses the preprocessor to change code before compilation.
If ENABLE_DEBUG is defined as 1, whenever the preprocessor sees
LOG_MSG("something happened");
It will replace it with
printf("something happened");
If it is defined as 0, or not defined it will replace it with nothing (as the other answer that has just been published says).

Resources