Comparator as function parameter - c

Is there any possibility in C89 to pass an operator as function parameter? I mean pass for expample <, ==, >= etc. Something like custom comparator in Java, but passed only with particular symbol. Maybe there is solution with special kind of preprocessor macro (I try to use '#' taken from processor macros)?
I know about pointers to functions, but I want something a little bit different.
Example:
void fun(int a, int b, comperator)
{
if(a comperator b)
........
}

You can use a macro. But remember - a macro is not a function; it has different (ugly) syntax, some specific problems, some advantages, etc.
Suppose you have a function:
int fun(int x, int y)
{
if (x < y)
return 1;
else if (x < 2 * y)
return 2;
else if (x < 2 * y)
return 3;
else
return 4;
}
To use a different comparator, first convert it to a macro:
#define FUN(x, y) \
x < y ? 1 : \
x < 2 * y ? 2 : \
x < 3 * y ? 3 : \
4
This conversion is very ugly (it will usually by more ugly than in my example), and not always possible, but now you can add a comparator:
#define FUN(x, y, c) \
x c y ? 1 : \
x c 2 * y ? 2 : \
x c 3 * y ? 3 : \
4
Usage:
printf("%d\n", FUN(3, 5, <));
(Note: in macros, you should add parentheses around variables, explained e.g. here; I omitted them for clarity).

No You cant , just pass it like a string and make a test in the function

The easiest way would be to use enums that represent the comparators but with some manipulation you could write a macro wrapper to fun() that calls funLT(), funGT... or enumerates the comparators to LT,GT,.. for use in a switch case.
If fun(...) is rather large you probably want to use enums and a switch case inside the function at the appropriate location.
enum{LT,GT,EQ,NE,LE,GE};
#define fun(a,b,OP) fun_(a,b,
(0 OP 1) \
? (1 OP 0) \
? NE \
: (0 OP 0) \
? LE \
: LT \
: (0 OP 0) \
? (1 OP 0) \
? GE \
: EQ \
: GT \
)
fun(int a, int b, int op){
//code
switch(op){
case GE: //etc...
}
//more code
}
If the function is small you may instead prefer to have separate functions for each operator
#define fun(a,b,OP) \
(0 OP 1) \
? (1 OP 0) \
? funNE((a),(b)) \
: (0 OP 0) \
? funLE((a),(b)) \
: funLT((a),(b)) \
: (0 OP 0) \
? (1 OP 0) \
? funGE((a),(b)) \
: funEQ((a),(b)) \
: funGT((a),(b))

Related

Use of comma vs do-while in C macro

Is there a downside to doing this:
#define get_and_mark(name, b) get_val(name, &b), b = b | 0x80
rather than this:
#define get_and_mark(name, b) \
do { \
get_val(name, &b); \
b = b | 0x80; \
} while (0)
As far as I can see, the comma should also be safe for use in loops, branches etc.
But is it really?
If fixed up as Gerhardh says:
#define get_and_mark(name, b) (get_val(name, &(b)), (b) = (b) | 0x80)
then the first version can be used in an expression such as:
if (get_and_mark(name, b) != 0)
but the second cannot. Which semantic do you want? Do you want the invocation in an if condition to be a compile-time error?
Note that since b is mentioned multiple times in the expansion, you can't use get_and_mark(name, b[i++]). Also, note that you could use (b) |= 0x80 for the assignment in both variants:
#define get_and_mark(name, b) (get_val(name, &(b)), (b) |= 0x80)
#define get_and_mark(name, b) \
do { \
get_val(name, &(b)); \
(b) |= 0x80; \
} while (0)
You could use the comma operator in the second variant — though there's no need to do so.
Why not use an inline function?
static inline int get_and_mark(const char *name, int *b)
{
get_val(name, b);
return (*b |= 0x80);
}
You'd invoke it with get_and_mark(name, &b)? (Obviously, I'm guessing at the type of name, but fixing that if I'm wrong is easy.)

Disable type-limits check for a macro

I'm trying to build a simple SIGNOF macro:
#define SIGNOF(a) ((a) < 0 ? -1 : 1)
If a is negative it should return -1, otherwise 1. If a is an unsigned type, it should always return 1 and the compiler can optimize away the negative code path.
However, GCC rightfully warns me that
error: comparison of unsigned expression in ‘< 0’ is always false [-Werror=type-limits]
29 | #define SIGNOF(a) ((a) < 0 ? -1 : 1)
But in this case I actually want this behavior. Is there any way to tell the compiler that this is intentional, similar to /* fall-though */ in a switch-case?
If your compiler supports it, you can use _Generic:
#define SIGNOF(a) _Generic(a, unsigned char: 1, \
unsigned short: 1, \
unsigned int: 1, \
unsigned long: 1, \
unsigned long long: 1, \
default: (a) < 0 ? -1 : 1)
What works is
static inline int __signof(long long a)
{
return a < 0 ? -1 : 1;
}
#define SIGNOF(a) _Generic(a, unsigned char: 1, \
unsigned short: 1, \
unsigned int: 1, \
unsigned long: 1, \
unsigned long long: 1, \
default: __signof(a))
This seems to fix the warning problem, at the expense of evaluating the operand twice:
#define SIGNOF(a) ((a) == 0 ? +1 : ((a) > 0) ? +1 : -1)
I observe that since the proposed DIV_ROUND() macro evaluates both its arguments twice, it also has problems if the arguments have side effects (increments, function calls, etc).
Time for a hideous workaround:
#define SIGNOF_(a) ((a) < 0 ? -1 : 1)
#ifdef __GNUC__
#define SIGNOF(a) ({ \
typeof(a) _a = (a); \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
int _r = SIGNOF_(_a); \
_Pragma("GCC diagnostic pop") \
_r; })
#else
#define SIGNOF(a) SIGNOF_(a)
#endif
It makes use of GNU C "statement expressions" (({ statements; })) and the typeof operator. The initialization _a = (a); is to catch any -Wtype-limit warnings in the macro parameter a before the warning is temporarily disabled by the pragmas.

Error in C preprocessor concatenation with variable and function (dynamically indexing in a for loop)

I ran this code in this compiler
#define CCc(n) CC_##n
#define CC(n) CCc(n)
#define CC_1 (1,2)
#define CC_2 (3,4)
#define CALL_FUNCTION(xy) Coord(xy)
#define YES 1
#define NO 0
int Coord(x, y){
if (x < 0.5 && y < 1.5){
return YES;
}
return NO;
}
int main()
{
for(int i = 1; i < 3; i++){
CALL_FUNCTION(CC(i));
}
return 0;
}
and got this error:
error: use of undeclared identifier 'CC_i'
Why does this error occur? And what is the right way to achieve this?
You cannot do run-time/variable evaluations in the pre-processor. It requires compile-time pre-processor tokens. So rather than trying to define a number of #define based on run-time values, you should gather all compile-time constants in one place.
A common way to do so is "X macros". In your case it might look like this:
#define CC_LIST \
/* n x y */ \
X(1, 1, 2) \
X(2, 3, 4) \
int main()
{
#define X(n,x,y) (void) Coord(x, y);
CC_LIST
#undef X
return 0;
}
This expands to (void) Coord(1,2); (void) Coord(3,4);, so it is a compile-time loop unrolling of sorts.
Alternatively, if you insist on having the "CC_N" macros because they are also needed for other purposes, you can do this:
#define CC_LIST \
/* n */ \
X(1) \
X(2) \
#define CC(n) CC_##n
#define CC_1 1,2
#define CC_2 3,4
#define CALL_FUNCTION(...) (void) Coord(__VA_ARGS__);
int main()
{
#define X(n) CALL_FUNCTION(CC(n))
CC_LIST
#undef X
return 0;
}
As you can tell, macro tricks like "X macros" are not easy to read and should be regarded as the last resort. Only use them when proper program re-design is not possible, for example during maintenance of existing code.

C macro evaluate at compile time

I need a Macro that would be evaluated at compile time, something like:
#define FIND_RANGE(x) \
if x>16 \
32 \
elif x>8 \
16 \
elif x>4 \
8 \
elif x>2 \
4 \
elif x>1 \
2 \
else \
1 \
endif \
So the code
#define S1 FIND_RANGE(7)
unsinged int i = S1;
would be sent to compiler as
unsinged int i = 8;
Can this simple algorithm be done so it is evaluated at compile time?
While C has no constexpr functions, both GCC and Clang can evaluate simple functions at compile-time with -O1. The related optimization is known as constant folding.
The following C code:
#include <stdio.h>
static inline unsigned int findRange(unsigned int x)
{
if (x > 16)
return 32;
else if (x > 8)
return 16;
else if (x > 4)
return 8;
else if (x > 2)
return 4;
else if (x > 1)
return 2;
return 1;
}
int main(void)
{
unsigned int i = findRange(7);
printf("%u\n", i);
return 0;
}
results into x86-64 assembly code (reference: godbolt.org/g/kVYe0u):
main:
sub rsp, 8
mov esi, 8
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
add rsp, 8
ret
As you can see, the call to findRange is subsituted by value, which is computed at compile-time.
This works even when findRange is defined as normal (non-inline) function with external linkage.
I don't think you can do that that easy. The problem is that the conditionals available to the preprocessor comes as preprocessor directives.
What you can do however is to use the #include directive creatively to create more advanced constructs. Create find-range.mac as:
#if x>16
32
#elif x>8
16
#elif x>4
8
#elif x>2
4
#elif x>1
2
#else
1
#endif
#undef x
and then use it as:
int i =
#define x 7
#include "find-range.mac"
;
Which should expand to something like:
int i =
8
;
Another trick that does not go all the way is to do replace FIND_RANGE(x) with FIND_RANGEx by gluing and then define FIND_RANGEx appropriately. This requires x to be in a finite set of values:
#define FIND_RANGE(x) FIND_RANGE ## x
#define FIND_RANGE1 1
#define FIND_RANGE2 2
#define FIND_RANGE3 4
#define FIND_RANGE4 4
#define FIND_RANGE5 8
#define FIND_RANGE6 8
#define FIND_RANGE7 8
#define FIND_RANGE8 8
// etc...
For a bit of recreation, I translated that bit twiddling hack mentioned by Sander into a macro:
#define XS(x,y) (x | (x>>y))
#define FR(x) XS(XS(XS(XS(XS(x-1,1),2),4),8),16)+1
So FR(7) should give 8 at compile time, and so on.
(*But for all practical purposes an answer by Grzegorz Szpetkowski is the one to refer to.)
Turns out it is doable, and even simple:
#define POW00 1.0f
#define POW01 2.0f
#define POW02 4.0f
#define POW03 8.0f
#define POW04 16.0f
#define POW05 32.0f
#define POW06 64.0f
#define POW07 128.0f
#define POW08 256.0f // use some nicer pow2 constant generation
#define SCALE(x) ( \
x > POW07 ? POW08 : \
x > POW06 ? POW07 : \
x > POW05 ? POW06 : \
x > POW04 ? POW05 : \
x > POW03 ? POW04 : \
x > POW02 ? POW03 : \
x > POW01 ? POW02 : \
x > POW00 ? POW01 : POW00 \
) // end SCALE
Example:
int main()
{
float a = (float)SCALE(7.0f);
}
This gets evaluated at compile time to
float a = 8.0f;

Conditional statements based on #define's name

I just started doing some C (coming from Java). I'm trying to figure out what the language's approach to a conditional based on a define's name is.
e.g. I have a huge header file that I can't(shouldn't) edit with a lot of defines.
#define GPIO_OTYPER_OT_0 ((uint32_t)0x00000001)
#define GPIO_OTYPER_OT_1 ((uint32_t)0x00000002)
#define GPIO_OTYPER_OT_2 ((uint32_t)0x00000004)
#define GPIO_OTYPER_OT_3 ((uint32_t)0x00000008)
#define GPIO_OTYPER_OT_4 ((uint32_t)0x00000010)
#define GPIO_OTYPER_OT_5 ((uint32_t)0x00000020)
And so on;
I want to make a function/declaration (or whatever to the solution is) to act on the _# part of the define.
(pseudocode)
void initialize(int X) {
GPIOA->MODER |= GPIO_MODER_MODER%X_5;
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_%X;
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR%X;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR5;
GPIOA->ODR |= GPIO_ODR_ODR_%X;
}
Where %X is int X
All I can think of is a switch statement for each X but X has a large range so the source file would be huge.
edit:
https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f4/lib/stm32f411xe.h
is the header file.
Use ST's GPIO abstraction layer, which can be found here. Notably, see GPIO_InitTypeDef which gives you a structure for what you're doing above, and GPIO_Init which will actually do what you want. The initialization structure takes pins as a bit mask, so as #artless noise suggested in a comment, you can just do 1<<X to create your mask. All the MCU-specific behavior and register mapping is hidden away from your code.
If you are trying to implement your own driver layer as an exercise or because you think the ST library is not very good, then I would still take a look at how they implemented GPIO_Init in the C file. They use shifting, but you'll note that when dealing with the registers, it is not always as easy as 1<<X (though, note that for their configuration structure it is always that easy). Some registers have multiple bits for each pin (mode: 2 bits, pull config: 2 bits, alternate function: 4 bits, split across multiple registers).
edit: I'm not suggesting adding more libraries that you don't already have. The library/code base you referenced the header file in already includes ST's peripheral library, so it makes sense (to me) to use it.
There is no way to insert an arbitrary integer into a macro name. However, your integers are going to be small (smaller than 32 for sure, because all your constants are of a 32-bit type). So you can convert a switch-statement into a one-line expression, like so:
x == 0 ? GPIO_OTYPER_OT_0 : \
x == 1 ? GPIO_OTYPER_OT_1 : \
x == 2 ? GPIO_OTYPER_OT_2 : \
...
x == 31 ? GPIO_OTYPER_OT_31 : 0
Here, you can even make a "default" expression that will generate a runtime error - something like (abort(), (uint32_t)0).
To make this more generic, separate the GPIO_OTYPER_OT_ part into a macro argument, and use the "paste operator" ##:
#define MY_MACRO(name, x) \
x == 0 ? name ## 0 : \
x == 1 ? name ## 1 : \
x == 2 ? name ## 2 : \
...
x == 31 ? name ## _31 : \
(abort(), name ## 0)
Usage example:
GPIOA->ODR |= MY_MACRO(GPIO_ODR_ODR_, x);
You have to make a separate macro for those names that have x in the middle:
#define MY_MACRO2(prefix, x, suffix) ( \
(x) == 0 ? prefix ## 0 ## suffix : \
(x) == 1 ? prefix ## 1 ## suffix : \
...
(x) == 31 ? prefix ## 31 ## suffix : \
(abort(), prefix ## 0 ## suffix))
Here I also added the necessary parentheses (around x and around the whole macro), like it is customary with C macros.
P.S. If your large header file doesn't define macros with numbers up to 31, but has a smaller limit, you cannot use the macro that mentions all these names, because you would get a compilation error. In that case, insert the maximum into the name of the macro. Then you can define them in a "recursive" way:
#define MY_MACRO_MAX1(prefix, x) \
x == 0 ? prefix ## 0 ## suffix : prefix ## 1 ## suffix
#define MY_MACRO_MAX2(prefix, x) \
x == 2 ? prefix ## 2 ## suffix : MY_MACRO_MAX1(prefix, x)
#define MY_MACRO_MAX3(prefix, x) \
x == 3 ? prefix ## 3 ## suffix : MY_MACRO_MAX2(prefix, x)
#define MY_MACRO_MAX4(prefix, x) \
x == 4 ? prefix ## 4 ## suffix : MY_MACRO_MAX3(prefix, x)
#define MY_MACRO_MAX5(prefix, x) \
x == 5 ? prefix ## 5 ## suffix : MY_MACRO_MAX4(prefix, x)
...

Resources