Skip to content

Instantly share code, notes, and snippets.

@bojanpotocnik
Last active March 22, 2017 07:38
Show Gist options
  • Save bojanpotocnik/8007bae05ad8d16b8a875457708d159c to your computer and use it in GitHub Desktop.
Save bojanpotocnik/8007bae05ad8d16b8a875457708d159c to your computer and use it in GitHub Desktop.
Various C utility macros
/*
* compiler_utils.h
*
* Created: 2016, 2017
* Author: Bojan Potocnik
* info@bojanpotocnik.com
*/
#ifndef COMPILER_UTILS_H__
#define COMPILER_UTILS_H__
#include <stddef.h> /*< size_t */
#include <float.h> /*< FLT_EPSILON */
#ifndef min
__attribute__((__const__, __unused__, __weak__))
static inline int min(const int a, const int b) {
return (a < b ? a : b);
}
#endif /* min */
#ifndef max
__attribute__((__const__, __unused__, __weak__))
static inline int max(const int a, const int b) {
return (a > b ? a : b);
}
#endif /* max */
#ifndef MIN
#define MIN(a, b) (a < b ? a : b)
#endif
#ifndef MAX
#define MAX(a, b) (a < b ? b : a)
#endif
#if defined(__CC_ARM)
/* Always set to 1 for the ARM compiler, even when you specify the --thumb option.
* Note: This macro is also defined if you invoke the ARM compiler using armcpp, tcc, and tcpp. */
#define WEAK __weak
#define STR(x) x
#define ATTR_ISR __attribute__((__used__))
#elif defined(__GNUC__)
/* These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran.
* Even when using ARM compiler, defined when the --gnu option is specified.
* It is an integer that shows the current major version of the GNU mode being used. */
#define WEAK __attribute__((__weak__))
/**
* @brief Print integer value of preprocessor macro (or it's name if value is not defined).
* GCC double expansion trick is used for stringifying the integer value.
*
* @param Preprocessor definition of integer value.
* @return Stringified representation of integer value.
*/
#define STR(x) _STR(x)
#define _STR(x) #x
#define ATTR_ISR __attribute__((__interrupt_handler__, __used__))
#endif
/**
* @brief Check if integer value is a power of 2.
*
* @param N An integer value to be checked.
*
* @return True if integer is a power of two.
*/
#define IS_POWER_OF_2(N) (((N) & ((N) - 1)) == 0)
/**
* @brief Calculate power of 2 (2 to the power of n).
*
* @param N A power (potency).
*
* @return Two to the power of n (2^n).
*/
#define POW_2(N) (1 << (N))
/**
* @brief Round a number (+0.5 = 1, -0.5 = -1). Cast to integer type is mandatory to achieve desired result.
*
* @param N The number to be rounded.
*
* @return Rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND(N) ( ((N) >= 0) ? (N) + 0.5f : (N) - 0.5f )
/**
* @brief Rounds up a positive number. Cast to integer type is mandatory to achieve desired result.
*
* @param N A positive number to be rounded.
*
* @return Up-rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_UP_POS(N) ( ((float) (N)) + (1.0f - FLT_EPSILON) )
/**
* @brief Rounds up a negative number. Cast to integer type is mandatory to achieve desired result.
*
* @param N A negative number to be rounded.
*
* @return Up-rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_UP_NEG(N) (N)
/**
* @brief Rounds down a positive number. Cast to integer type is mandatory to achieve desired result.
*
* @param N A positive number to be rounded.
*
* @return Down-rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_DOWN_POS(N) (N)
/**
* @brief Rounds down a negative number. Cast to integer type is mandatory to achieve desired result.
*
* @param N A negative number to be rounded.
*
* @return Down-rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_DOWN_NEG(N) ( ((float) (N)) - (1.0 - FLT_EPSILON) )
/**
* @brief Rounds a number up. Cast to integer type is mandatory to achieve desired result.
*
* @param N A number to be rounded.
*
* @return Up-rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_UP(N) ( ((N) >= 0) ? ROUND_UP_POS(N) : ROUND_UP_NEG(N) )
/**
* @brief Rounds a number down. Cast to integer type is mandatory to achieve desired result.
*
* @param N A number to be rounded.
*
* @return Down-rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_DOWN(N) ( ((N) >= 0) ? ROUND_DOWN_POS(N) : ROUND_DOWN_NEG(N) )
/**
* @brief Rounds a number towards 0. Cast to integer type is mandatory to achieve desired result.
*
* @param N A number to be rounded.
*
* @return Rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_TOWARDS_0(N) ( ((N) >= 0) ? ROUND_DOWN_POS(N) : ROUND_UP_NEG(N) )
/**
* @brief Rounds a number away from 0. Cast to integer type is mandatory to achieve desired result.
*
* @param N A number to be rounded.
*
* @return Rounded number. Cast to integer type is mandatory to achieve desired result.
*/
#define ROUND_AWAY_FROM_0(N) (((N) >= 0) ? ROUND_UP_POS(N) : ROUND_DOWN_NEG(N))
#if 0
// TODO
/**
* @brief Rounds a positive number up to the nearest multiple of significance.
*
* @param N A positive number to be rounded.
* @param s The multiple to which the number is to be rounded.
*
* @return Up-rounded number (the smallest possible z which satisfies: z * y >= x).
*/
#define CEILING(N, S) (((x) + (s) - 1) / (s))
/**
* @brief Rounds a positive number up to the nearest multiple of significance.
*
* @param x A positive number to be rounded.
* @param s The multiple to which the number is to be rounded.
*
* @return Up-rounded number (the smallest possible z which satisfies: z * y >= x).
*/
#define ROUND_UPfff(N, S) ((((N) + (S) - 1) / (S)) * (S))
#endif
/**
* @brief Generates compiler error if condition is 0 or false.
*
* Original version generates compiler error if condition is not exactly 0.
* ((void)sizeof(char[1 - 2*!!(condition)]))
*/
#define ASSERT_BUG(condition, description) ((void)sizeof(char[1 - 2*!!((unsigned char) !(condition))]))
/**
* @brief Generates compiler error if condition is 0 or false.
*/
#define ASSERT_BUG_FUNCTION(condition, description) \
static inline __attribute__((__unused__, __always_inline__)) \
void __compiler_assert_##__FILE__##__LINE__(void) { \
ASSERT_BUG(condition, description); \
}
/**
* @brief Get length of the array.
*
* Taken from Google Chromium's codebase.
* This version improves on the array[0] or *array version by using 0[array], which is equivalent
* to array[0] on plain arrays, but will fail to compile if array happens to be a C++ type that
* overloads operator[]().
* Also, if a pointer is mistakenly passed as the argument, the compiler will complain in some
* cases - specifically if the pointer's size isn't evenly divisible by the size of the object
* the pointer points to. In that situation a divide-by-zero will cause the compiler to error out.
* The division causes a divide-by-zero operation (that should be caught at compile time since
* it's a compile-time constant expression) for many (but not all) situations where a pointer is
* passed as the array parameter.
*
* @return Count of the array elements.
*/
#define COUNT_OF(array) ((sizeof(array) / sizeof(0[array])) / ((size_t)(!(sizeof(array) % sizeof(0[array])))))
/**
* @brief Get size (in bytes) of the member of the structure.
*
* The operand of sizeof is not evaluated, so there is no issue with dereferencing the null
* pointer (because it isn't actually dereferenced).
*
* @return sizeof() of the member of the structre.
*/
#define sizeof_member(type, member) sizeof(((type *)0)->member)
// TODO:
#define ABS(x) ((x) < 0 ? -(x) : (x))
#endif /* COMPILER_UTILS_H__ */
/* [] END OF FILE */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment