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.
Let's say I have 2 sets of values for P_A, P_B, P_C as below
#define X_P_A 2
#define X_P_B 3
#define X_P_C 4
#define Y_P_A 5
#define Y_P_B 6
#define Y_P_C 7
There are 3 types of users:- once that only need X variants, once that only need Y variants and once those may need both.
eg
#ifdef X
#define P_A X_P_A
#define P_B X_P_B
#define P_C X_P_C
#endif
#ifdef Y
#define P_A Y_P_A
#define P_B Y_P_B
#define P_C Y_P_C
#endif
Users that need both will make the decision at run time and call X_P_<> or Y_P_<> as needed.
Is there a way to make it simpler, so that I don't have to write conditional macros for each field
ifdef X
// do something magical does defines all P_<> to X_P_<>
#endif
I know it sounds stupid. You may ask why not just use X_P_<> variants on X. I am just trying to understand if it is possible.
I am okay with changing the way the macros the defined.
Is something similar to below code possible : (problem with below code is that compilation fails because #if not allowed within #define)
#define A 1
#define B 2
#define C 3
/* Not a correct #define macro */
#define X_P(x) \
#if(x == A) 2 \
#elif(x == B) 3 \
#elif(x == C) 4 \
#endif
#ifdef X
#define P(x) X_P(x)
#endif
You could do it with one variant of X-Macros:
#define IMPLEMENT(X) \
X(P_A, 1, 5) \
X(P_B, 2, 6) \
X(P_C, 3, 7)
enum {
// Just one
#define X1_P(n, x, y) n = x,
IMPLEMENT(X1_P)
// Both
#define X2_P(n, x, y) X_##n = x,
#define Y2_P(n, x, y) Y_##n = y,
IMPLEMENT(X2_P)
IMPLEMENT(Y2_P)
DUMMY // Just in case compiler is strict about trailing comma
};
Which would expand to:
enum {
P_A = 1, P_B = 2, P_C = 3,
X_P_A = 1, X_P_B = 2, X_P_C = 3,
Y_P_A = 5, Y_P_B = 6, Y_P_C = 7,
DUMMY
};
#define X_P(x) ((x) - 0x10 + 1) // 1 is 0x31 and A is 0x41 hence A will give 0x41 - 0x10 + 1 = 0x32
#define Y_P(y) ((y) - 0x10 + 5) // same logic applies
Would it be what you are looking for ? Not fully answering your question though
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))
I need to find the Max value with a macro beetween 55 values defined also as macro definitions. I mean
#define VALUE1 56
#define VALUE2 76
...
#define VALUE55 14
#define MAX_BEETWEEN_VALUES (...) ...
the macro function MAX_BEETWEEN_VALUES should return 76 as result.
I can´t figure out how this macro should be coded.
Thanks for your help
Here's another C kludge to find the maximum at compile-time. Assuming that enumerations work as well as #defines for you and that the values are small positive integers (though there are even worse workarounds for other domains).
union value_set_t {
# define V(name, value) char name##_[value];
# include "values.h"
# undef V
};
enum {
# define V(name, value) name = value,
# include "values.h"
# undef V
MAX_BETWEEN_VALUES = sizeof(union value_set_t)
};
With values.h:
V(VALUE1, 56)
V(VALUE2, 76)
V(VALUE55, 14)
Code for my comment to answer above: https://stackoverflow.com/a/20221017/2963099
V1 to V58 not shown
#define V59 1
#define V60 33
#define V61 1
#define V62 2
#define V63 1
#define V64 2
#define MAX2(a,b) ((a>b)?(a):(b))
#define MAX4(a,b,c,d) MAX2(MAX2(a,b), MAX2(c,d))
#define MAX8(a,b,c,d,e,f,g,h) MAX2(MAX4(a,b,c,d),MAX4(e,f,g,h))
#define MAX64(a1,a2,a3,a4,a5,a6,a7,a8, \
b1,b2,b3,b4,b5,b6,b7,b8, \
c1,c2,c3,c4,c5,c6,c7,c8, \
d1,d2,d3,d4,d5,d6,d7,d8, \
e1,e2,e3,e4,e5,e6,e7,e8, \
f1,f2,f3,f4,f5,f6,f7,f8, \
g1,g2,g3,g4,g5,g6,g7,g8, \
h1,h2,h3,h4,h5,h6,h7,h8) MAX8(\
MAX8(a1,a2,a3,a4,a5,a6,a7,a8), \
MAX8(b1,b2,b3,b4,b5,b6,b7,b8), \
MAX8(c1,c2,c3,c4,c5,c6,c7,c8), \
MAX8(d1,d2,d3,d4,d5,d6,d7,d8), \
MAX8(e1,e2,e3,e4,e5,e6,e7,e8), \
MAX8(f1,f2,f3,f4,f5,f6,f7,f8), \
MAX8(g1,g2,g3,g4,g5,g6,g7,g8), \
MAX8(h1,h2,h3,h4,h5,h6,h7,h8))
int main(int, char**)
{
int x= MAX64(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21,V22,V23,V24,V25,V26,V27,V28,V29,V30,V31,V32,V33,V34,V35,V36,V37,V38,V39,V40,V41,V42,V43,V44,V45,V46,V47,V48,V49,V50,V51,V52,V53,V54,V55,V56,V57,V58,V59,V60,V61,V62,V63,V64);
return x;
}
Compiles pretty quickly (and has 33 as correct answer)
Hard code
#define MAX(X, Y) ((X>Y)?(X):(Y))
#define MAX_BEETWEEN_VALUES MAX(VALUE1, \
MAX(VALUE2, \
MAX(VALUE3, \
... \
MAX(VALUE54, \
VALUE55))) ... )
~~~~~~~~~ 54 close parenthesis
It may exceed compiler's limitations.
A novel (and fairly evil) approach to generating having many/max macros could be to generate them.
Example Python script:
def minmax(a, expr):
t = "("
t = t + ("(%s%s%s)?" % (a[0], expr, a[1]))
if len(a) == 2:
r_a = a[0]
r_b = a[1]
else:
r_a = minmax((a[0],) + a[2:], expr)
r_b = minmax(a[1:], expr)
t = t + ("%s:%s" % (r_a, r_b))
return t + ")"
for i in range(2, 8):
args = tuple([("v%d" % j) for j in range(i)])
print((" #define MIN%d(%s) " % (i, ",".join(args)) + minmax(args, "<")))
print((" #define MAX%d(%s) " % (i, ",".join(args)) + minmax(args, ">")))
generates this...
#define MIN2(v0,v1) ((v0<v1)?v0:v1)
#define MAX2(v0,v1) ((v0>v1)?v0:v1)
#define MIN3(v0,v1,v2) ((v0<v1)?((v0<v2)?v0:v2):((v1<v2)?v1:v2))
#define MAX3(v0,v1,v2) ((v0>v1)?((v0>v2)?v0:v2):((v1>v2)?v1:v2))
#define MIN4(v0,v1,v2,v3) ((v0<v1)?((v0<v2)?((v0<v3)?v0:v3):((v2<v3)?v2:v3)):((v1<v2)?((v1<v3)?v1:v3):((v2<v3)?v2:v3)))
#define MAX4(v0,v1,v2,v3) ((v0>v1)?((v0>v2)?((v0>v3)?v0:v3):((v2>v3)?v2:v3)):((v1>v2)?((v1>v3)?v1:v3):((v2>v3)?v2:v3)))
#define MIN5(v0,v1,v2,v3,v4) ((v0<v1)?((v0<v2)?((v0<v3)?((v0<v4)?v0:v4):((v3<v4)?v3:v4)):((v2<v3)?((v2<v4)?v2:v4):((v3<v4)?v3:v4))):((v1<v2)?((v1<v3)?((v1<v4)?v1:v4):((v3<v4)?v3:v4)):((v2<v3)?((v2<v4)?v2:v4):((v3<v4)?v3:v4))))
#define MAX5(v0,v1,v2,v3,v4) ((v0>v1)?((v0>v2)?((v0>v3)?((v0>v4)?v0:v4):((v3>v4)?v3:v4)):((v2>v3)?((v2>v4)?v2:v4):((v3>v4)?v3:v4))):((v1>v2)?((v1>v3)?((v1>v4)?v1:v4):((v3>v4)?v3:v4)):((v2>v3)?((v2>v4)?v2:v4):((v3>v4)?v3:v4))))
#define MIN6(v0,v1,v2,v3,v4,v5) ((v0<v1)?((v0<v2)?((v0<v3)?((v0<v4)?((v0<v5)?v0:v5):((v4<v5)?v4:v5)):((v3<v4)?((v3<v5)?v3:v5):((v4<v5)?v4:v5))):((v2<v3)?((v2<v4)?((v2<v5)?v2:v5):((v4<v5)?v4:v5)):((v3<v4)?((v3<v5)?v3:v5):((v4<v5)?v4:v5)))):((v1<v2)?((v1<v3)?((v1<v4)?((v1<v5)?v1:v5):((v4<v5)?v4:v5)):((v3<v4)?((v3<v5)?v3:v5):((v4<v5)?v4:v5))):((v2<v3)?((v2<v4)?((v2<v5)?v2:v5):((v4<v5)?v4:v5)):((v3<v4)?((v3<v5)?v3:v5):((v4<v5)?v4:v5)))))
#define MAX6(v0,v1,v2,v3,v4,v5) ((v0>v1)?((v0>v2)?((v0>v3)?((v0>v4)?((v0>v5)?v0:v5):((v4>v5)?v4:v5)):((v3>v4)?((v3>v5)?v3:v5):((v4>v5)?v4:v5))):((v2>v3)?((v2>v4)?((v2>v5)?v2:v5):((v4>v5)?v4:v5)):((v3>v4)?((v3>v5)?v3:v5):((v4>v5)?v4:v5)))):((v1>v2)?((v1>v3)?((v1>v4)?((v1>v5)?v1:v5):((v4>v5)?v4:v5)):((v3>v4)?((v3>v5)?v3:v5):((v4>v5)?v4:v5))):((v2>v3)?((v2>v4)?((v2>v5)?v2:v5):((v4>v5)?v4:v5)):((v3>v4)?((v3>v5)?v3:v5):((v4>v5)?v4:v5)))))
#define MIN7(v0,v1,v2,v3,v4,v5,v6) ((v0<v1)?((v0<v2)?((v0<v3)?((v0<v4)?((v0<v5)?((v0<v6)?v0:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6))):((v3<v4)?((v3<v5)?((v3<v6)?v3:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6)))):((v2<v3)?((v2<v4)?((v2<v5)?((v2<v6)?v2:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6))):((v3<v4)?((v3<v5)?((v3<v6)?v3:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6))))):((v1<v2)?((v1<v3)?((v1<v4)?((v1<v5)?((v1<v6)?v1:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6))):((v3<v4)?((v3<v5)?((v3<v6)?v3:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6)))):((v2<v3)?((v2<v4)?((v2<v5)?((v2<v6)?v2:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6))):((v3<v4)?((v3<v5)?((v3<v6)?v3:v6):((v5<v6)?v5:v6)):((v4<v5)?((v4<v6)?v4:v6):((v5<v6)?v5:v6))))))
#define MAX7(v0,v1,v2,v3,v4,v5,v6) ((v0>v1)?((v0>v2)?((v0>v3)?((v0>v4)?((v0>v5)?((v0>v6)?v0:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6))):((v3>v4)?((v3>v5)?((v3>v6)?v3:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6)))):((v2>v3)?((v2>v4)?((v2>v5)?((v2>v6)?v2:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6))):((v3>v4)?((v3>v5)?((v3>v6)?v3:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6))))):((v1>v2)?((v1>v3)?((v1>v4)?((v1>v5)?((v1>v6)?v1:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6))):((v3>v4)?((v3>v5)?((v3>v6)?v3:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6)))):((v2>v3)?((v2>v4)?((v2>v5)?((v2>v6)?v2:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6))):((v3>v4)?((v3>v5)?((v3>v6)?v3:v6):((v5>v6)?v5:v6)):((v4>v5)?((v4>v6)?v4:v6):((v5>v6)?v5:v6))))))
The macro doubles in length with each argument added, so I wouldn't recommend this for large arrays. however if all values are literals the compiler will likely resolve the result for you.
There might be a standardized way, but if not it's easy enough to just do it, if you're willing to go the "a better C" route.
#include <cstdio>
template<int a, int ...list> struct greatest_of {
static const int value = a > greatest_of<list...>::value
? a : greatest_of<list...>::value;
};
template<int a> struct greatest_of<a> {
static const int value = a;
};
int main()
{
printf("%d\n",greatest_of<1,2,3>::value);
}
(edit: printf).