Compare defined expressions as text - c

Say I have a set of defines arranged this way:
#define Var0 ((uint32_t)0x00001)
#define Var1 ((uint32_t)0x00002)
#define Var2 ((uint32_t)0x00004)
and later in the code I have this:
#define CurrVar Var1
When I attempt to compare:
#if (CurrVar != Var1)
#error "CurrVar" has to be "Var1" for this code to work
#endif
I get:
error: token is not a valid binary operator in a preprocessor subexpression
I cannot change values of VarX since those are part of a library, but I need to make sure that a proper value is used in the code at compile time.
Is there a way to compare those expressions?
Even if it will be compared as text, like this:
"((uint32_t)0x00002)" <> "((uint32_t)0x00002)"
or
"Var1" <> "Var1"
etc

Use _Static_assert, which is in standard C from 2011 on:
_Static_assert(CurrVar == Var1, "CurrVar is not equal to Var1.");
If you must use a pre-2011 implementation of C, a common kludge is to declare an array type with an expression that is negative if an assertion fails, causing the compiler to complain about the array size:
typedef char CurrVarIsNotEqualToVar1[CurrVar == Var1 ? 1 : -1];

You can't use anything C related in such operations. Preprocessor does not understand casts and it does not compare strings.
https://godbolt.org/z/X2xuPa
#include <stdint.h>
#define V1 1
#define V2 2
#define V3 3
#define CV V1
#if CV==V1
void foo(void)
{
printf("V1\n");
}
#else
void foo(void)
{
printf("not V1\n");
}
#endif
int main(void)
{
foo();
}

Related

A homework is about use macro

This questions is about my homework.
This topic is need to use like:
#define GENERIC_MAX(type)\
type type##_max(type x, type y)\
{\
return x > y ? x : y;\
}
The content of the question is to make this code run normally:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
The result of the operation is like this:
i=5.2000
j=3
And this code is my current progress, but there are have problems:
#include <stdio.h>
#define printname(n) printf(#n);
#define GenerateShowValueFunc(type)\
type showValue_##type(type x)\
{\
printname(x);\
printf("=%d\n", x);\
return 0;\
}
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
I don’t know how to make the output change with the type, and I don’t know how to display the name of the variable. OAO
This original task description:
Please refer to ShowValue.c below:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Through [GenerateShowValueFunc(double)] and [GenerateShowValueFunc(int)] these two lines macro call, can help us to generated as [showValue_double( double )] and [showValue_int( int )] function, And in main() function called. The execution result of this program is as follows:
i=5.2000
j=3
Please insert the code that defines GenerateShowValueFunc macro into the appropriate place in the ShowValue.c program, so that this program can compile and run smoothly.
A quick & dirty solution would be:
type showValue_##type(type x)\
{\
const char* double_fmt = "=%f\n";\
const char* int_fmt = "=%d\n";\
printname(x);\
printf(type##_fmt, x);\
return 0;\
}
The compiler will optimize out the variable that isn't used, so it won't affect performance. But it might yield warnings "variable not used". You can add null statements like (void)double_fmt; to silence it.
Anyway, this is all very brittle and bug-prone, it was never recommended practice to write macros like these. And it is not how you do generic programming in modern C. You can teach your teacher how, by showing them the following example:
#include <stdio.h>
void double_show (double d)
{
printf("%f\n", d);
}
void int_show (int i)
{
printf("%d\n", i);
}
#define show(x) _Generic((x),\
double: double_show, \
int: int_show) (x) // the x here is the parameter passed to the function
int main()
{
double i = 5.2;
int j = 3;
show(i);
show(j);
}
This uses the modern C11/C17 standard _Generic keyword, which can check for types at compile-time. The macro picks the appropriate function to call and it is type safe. The caller doesn't need to worry which "show" function to call nor that they pass the correct type.
Without changing the shown C-code (i.e. only doing macros), which I consider a requirement, the following code has the required output:
#include <stdio.h>
#define showValue_double(input) \
showValueFunc_double(#input"=%.4f\n" , input)
#define showValue_int(input) \
showValueFunc_int(#input"=%d\n" , input)
#define GenerateShowValueFunc(type) \
void showValueFunc_##type(const char format[], type input)\
{\
printf(format, input); \
}
/* ... macro magic above; */
/* unchangeable code below ... */
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Output:
i=5.2000
j=3
Note that I created something of a lookup-table for type-specific format specifiers. I.e. for each type to be supported you need to add a macro #define showValue_ .... This is also needed to get the name of the variable into the output.
This uses the fact that two "strings" are concatenated by C compilers, i.e. "A""B" is the same as "AB". Where "A" is the result of #input.
The rest, i.e. the required function definition is very similar to the teacher-provided example, using the ## operator.
Note, this is if the variable name has to correctly be mentioned in the output.
With out the i = things would be easier and would more elegantly use the generated functions WITHOUT having the called showValue_double(i); be explicit macros. I.e. the functions generated are 1:1 what is called from main(). I think that might be what is really asked. Let me know if you want that version.

C variable type assert

uint32_t fail_count = 0;
...
if(is_failed)
if(fail_count < UINT32_MAX - 1 )
++fail_count;
It works fine, but this code is fragile. Tomorrow, I may change the type of fail_count from uint32_t to int32_t and I forget to update UINT32_MAX.
Is there any way to assert fail_count is a uint32_t at the function where I have written my ifs?
P.S. 1- I know it is easy in C++ but I'm looking for a C way.
P.S. 2- I prefer to use two asserts than relying on the compiler warnings. Checking the number size via sizeof should work but is there any way to distinguish if type is unsigned?
As of C11, you can use a generic selection macro to produce a result based on the type of an expression. You can use the result in a static assertion:
#define IS_UINT32(N) _Generic((N), \
uint32_t: 1, \
default: 0 \
)
int main(void) {
uint32_t fail_count = 0;
_Static_assert(IS_UINT32(fail_count), "wrong type for fail_count");
}
You could of course use the result in a regular assert(), but _Static_assert will fail at compile time.
A better approach could be dispatching the comparison based on type, again using generic selection:
#include <limits.h>
#include <stdint.h>
#define UNDER_LIMIT(N) ((N) < _Generic((N), \
int32_t: INT32_MAX, \
uint32_t: UINT32_MAX \
) -1)
int main(void) {
int32_t fail_count = 0;
if (UNDER_LIMIT(fail_count)) {
++fail_count;
}
}
As you mentioned GCC, you can use a compiler extension to accomplish this in case you are not using C11:
First write a macro that emulates the C++ is_same. And then call it with the types you want to compare.
A minimal example for your particular case:
#include<assert.h>
#define is_same(a, b) \
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
int main()
{
int fail_count = 0;
is_same(fail_count, unsigned int);
}
The compiler asserts:
<source>: In function 'main':
<source>:4:3: error: static assertion failed: "fail_count is not unsigned int"
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
^~~~~~~~~~~~~
<source>:9:5: note: in expansion of macro 'is_same'
is_same(fail_count, unsigned int);
^~~~~~~
See Demo
What about a low-tech solution that works even with K&R C and any compiler past and present?
Place the right comment in the right place:
/*
* If this type is changed, don't forget to change the macro in
* if (fail_count < UINT32_MAX - 1) below (or file foobar.c)
*/
uint32_t fail_count = 0;
With a proper encapsulation this should refer to exactly one place in the code.
Don't tell me you increment the fail count in many places. And if you do, what
about a
#define FAIL_COUNT_MAX UINT32_MAX
right next to the declaration? That's more proper and clean code anyway.
No need for all the assertion magic and rocket sciencery :-)

variable name as macro argument

I am trying to create a macro in c, that will take a variable name, and declare it. I could call it like this:
MY_MACRO(test);
Would produce:
int test;
In order to achieve this I went this way:
#define MY_MACRO(var) /
int ##var; /
But the compiler doesn't understand this. Does such syntax exist in C11?
I wouldn't recommend doing such a thing. Anyway, there are two problems. First of all, to skip a newline, you need \, not /.
Second, the ## is wrong. What it does is concatenating the var to the int. So with MY_MACRO(foo) you would get intfoo;, but you want int foo;
The macro needs to be like this:
#define MY_MACRO(var) \
int var
## is not applicable here as it concatenates the token with something else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MY_MACRO(var) int var
or
#define MY_MACRO(var) \
int var \
void foo(void)
{
MY_MACRO(a);
a = rand();
printf("%d\n",a);
}
## pastes two tokens together into one token.
#define poem(var)\
int jack##var;
// Produces 'int jacksprat;'
poem(sprat)
In your case you don't need to do anything special at all, you can just use the argument directly:
#define MY_MACRO(var)\
int var;
The correct syntax would be something along the lines of this:
#define MY_MACRO(ident) \
int ident
int main() {
MY_MACRO(test);
test =42;
return test;
}
However, have you been looking into typedefs? Unlike typedefs, macros are considered bad practice.

Initializing a const variable with ntohl()

I'm trying to initialize a global-scoped const variable with a value that is byte-swapped appropriately.
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
const uint32_t a = ntohl(0x11223344);
int main(int argc, char const *argv[])
{
printf("%08x\n", a);
return 0;
}
Using gcc this fails with "error: initializer element is not constant". Yeah, okay, so the gcc header has ntohl() defined as a function or as "do {...} while (0)" or something similar that can't be evaluated at compile time. Bummer.
Is there anything I can do which will achieve the same end? I need to initialize the value for the appropriate endedness, and I want it to be a globally-scoped const. Is there any way to convince gcc to do this, short of rolling my own ntohl-like macro?
(BTW, I note that clang has ntohl() defined such that it can be evaluated at compile time. The above code sample works perfectly with clang. Unfortunately I don't get my pick of compilers.)
Section 6.7.8/4 of the standard reads
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
A call to ntohl is neither a constant expression nor a string literal. You can’t get there from here.
But global variables are bad anyway, and I suspect this may be a premature optimization. The easy fix is to use the expression directly in your code, which will have no effect at all on big-endian platforms, e.g.,
void foo(void)
{
const unit32_t a = ntohl(0x11223344);
/* ... */
}
Even better, use a preprocessor macro, as in
#define POTRZEBIE ntohl(0x11223344)
void bar(void)
{
const unit32_t a = POTRZEBIE;
/* ... */
}
On variables with automatic storage, the const qualifier means single assignment, so there is no problem with the above usage.
Initialize it in main() or use something like (assuming Linux):
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
const uint32_t a = 0x44332211;
#else
const uint32_t a = 0x11223344;
#endif
or perhaps
#include <endian.h>
#define A_ADDR 0x11223344
#if __BYTE_ORDER == __LITTLE_ENDIAN
const uint32_t a = __bswap_constant_32(A_ADDR);
#else
const uint32_t a = A_ADDR;
#endif

Stringification Parentheses Elimination

In c I have the following in an existing code base:
#define MYVAR (1)
As you can see this is conforming good practices in C by surrounding the #define with parenthesis (even though I know in this case it makes no difference since the value is not
an expression). Regardless I would like to use this in stringification. when I do this:
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
const char* mystring = TO_STRING(MYVAR) ;
The resultant string is "(1)". I'd like to eliminate the parentheses without doing the simple:
#define MYVAR 1
Is there anyway to eliminate parentheses during stringification in c?
Just use STRINGIFY x instead of STRINGIFY(x)
#include <stdio.h>
#define MYVAR 1
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY x
int main(void)
{
const char *mystring = TO_STRING(MYVAR);
printf("%s\n", mystring);
return 0;
}
TO_STRING(x) expands to STRINGIFY (1) when MYVAR is defined as (1)
If MYVAR is defined as 1 without parentheses you get a compile time error.

Resources