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> // for CHAR_MIN
#include <tgmath.h> // for copysign

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.


CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000