Handy macros (C)

From LiteratePrograms
Jump to: navigation, search

This article is a collection of useful C oneliners and macros. Each item in the collection includes some minimal code which demonstrates how the item can be used.

Contents

[edit] Bound a value

Makes sure that value stays within the max - min range. The macro makes use of temporary variables ("TEMP_whatever__") to avoid possible side effects from evaluating an expression more than once (e.g., i++ increments i every time it is evaluated).

The logic behind this macro is IF value < MIN THEN value=MIN ELSE (IF value > MAX THEN value=MAX ELSE value=value)

<<macro_bounds.c>>=

#include <stdio.h>

#define bounds(value, min, max)  ((TEMP_VALUE__=(value))>(TEMP_MAX__=(max))?TEMP_MAX__:(TEMP_VALUE__<(TEMP_MIN__=(min))?TEMP_MIN__:TEMP_VALUE__))

int main(void)
{
  int n;
  int TEMP_VALUE__, TEMP_MAX__, TEMP_MIN__;
  for(n=0; n<10; n++)
  {
    printf("n = %d Adjusted: %d\n", n, bounds(n,3,6));
  }
  return 0;
}

[edit] Test for even numbers

Check if a non-negative integer is even (2, 4, 6, 8, 10, etc.). It also works for negative integers if the processor represents integers in two's complement form, as is typically the case.

<<macro_iseven.c>>=
#include <stdio.h>

#define iseven(value) (!((value)&0x01))

int main(void)
{
 int n;
 for(n=0; n<65; n++)
 {
  printf("%d is%s even\n", n, iseven(n)?"":" not");
 }
 return 0;
}

[edit] Test for powers of two

Check if a positive integer is power of two (2, 4, 8, 16, 32, 64, etc.). The macro makes use of a temporary variable ("TEMP_VALUE__") to avoid possible side effects from evaluating an expression more than once (e.g., i++ increments i every time it is evaluated).

<<macro_powoftwo.c>>=

#include <stdio.h>

#define ispoweroftwo(value) ((TEMP_VALUE__=(value))&&!((TEMP_VALUE__-1)&TEMP_VALUE__))

int main(void)
{
  int n;
  int TEMP_VALUE__;
  for(n=0; n<65; n++)
  {
    printf("%d is%s power of two\n",n,ispoweroftwo(n)?"":" not");
  }
  return 0;
}

[edit] Xor swap

Xor swap is an idiom for swapping two variables without using a temporary variable. Generally its use is no longer recommended, as compilers are better able to choose the best swap implementation in a machine-specific way.

<<macro_xorswap.c>>=

#include <stdio.h>

#define xorswap(a, b) ((a)^=(b),(b)^=(a),(a)^=(b))

int main()
{
  int n1=5;
  int n2=7;

  printf("Before xorswap() n1=%d, n2=%d\n", n1, n2);
  xorswap(n1, n2);
  printf("After xorswap() n1=%d, n2=%d\n", n1, n2);

  return 0;
}

[edit] Set other than 0 to 1

Set all values other than 0 to 1.

<<macro_clamptoone.c>>=

#include <stdio.h>

#define clamptoone(value) (!!(value))

int main(void)
{
  int n;
  for(n=0; n<4; n++)
  {
    printf("n = %d clamped = %d\n",n,clamptoone(n));
  }
  return 0;
}

Download code
hijacker
hijacker
hijacker
hijacker