You can use copysign(1.0f, v)
to get
the sign of a real floating-point value v
. Apart from that, C has no built-in support for
the mathematical function signum, so you have to write your own. For
example:
int signum(int v) { if (v < 0) return -1; if (v > 0) return +1; return 0; }
int signum(int v) { return v < 0 ? -1 : v > 0 ? +1 : 0; }
A macro would be type-generic:
#define signum(v) ((v) < 0 ? -1 : (v) > 0 ? +1 : 0)
…but it can't take an expression with side-effects, and it might produce warnings when used with an unsigned integer type.
The following implementation is based on a recommended answer on Stack Overflow:
int signum(int v) { return (v > 0) - (v < 0); }
An attempt at a generic implementation for C11 could look like this:
#include<limits.h>
// forCHAR_
#includeMIN <tgmath.h>
// forcopysign
inline int signum(int v) { return (v > 0) - (v < 0); } inline long lsignum(long v) { return (v > 0) - (v < 0); } inline long long llsignum(long long v) { return (v > 0) - (v < 0); } #define signum(V) _Generic((V), \ signed char : (signum)(V), \ char : CHAR_MIN == 0 ? ((V) > 0) : (signum)(V), \ short : (signum)(V), \ int : (signum)(V), \ long : (lsignum)(V), \ long long : (llsignum)(V), \ unsigned char : (V) > 0, \ unsigned short : (V) > 0, \ unsigned : (V) > 0, \ unsigned long : (V) > 0, \ unsigned long long : (V) > 0, \ default : copysign(1.0f, (V)))
There might be problems with a type alias like ptrdiff_t
if it does not
alias a standard integer type.