Skip to main content
C23 update
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97

Rumor is that the next version of C will disallow sign magnitude and ones' complement signed integer encoding. True or not, it seems efficient to not have to code and test for those rare encodings.
[Edit 2025] C23 now only allows 2's complement encoding for signed integers.

Rumor is that the next version of C will disallow sign magnitude and ones' complement signed integer encoding. True or not, it seems efficient to not have to code and test for those rare encodings.

Rumor is that the next version of C will disallow sign magnitude and ones' complement signed integer encoding. True or not, it seems efficient to not have to code and test for those rare encodings.
[Edit 2025] C23 now only allows 2's complement encoding for signed integers.

added 176 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97

Future readers concerning spelling and grammar in this post: Although they should get corrected in an answer, edits to the question's code are not site appropriate.

Future readers concerning spelling and grammar in this post: Although they should get corrected in an answer, edits to the question's code are not site appropriate.

Rollback to Revision 3
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
/*
 * unicorn.h
 * Various tests to detect old and strange compilers.
 *
 *  Created on: Mar 8, 2019
 *      Author: chux
 */

#ifndef UNICORN_H_
#define UNICORN_H_

#include <assert.h>
#ifndef static_assert
  #define static_assert( e, m ) typedef char _brevit_static_assert[!!(e)]
#endif

#include <float.h>
#include <limits.h>
#include <stdint.h>

/*
 *  Insure 2's complement
 *  Could also check various int_leastN_t, int_fastN_t
 */
static_assert(SCHAR_MIN < -SCHAR_MAX && SHRT_MIN < -SHRT_MAX &&
    INT_MIN < -INT_MAX && LONG_MIN < -LONG_MAX &&
    LLONG_MIN < -LLONG_MAX && INTMAX_MIN < -INTMAX_MAX &&
    INTPTR_MIN < -INTPTR_MAX && PTRDIFF_MIN < -PTRDIFF_MAX
    , "Dinosaur"Dinosuar: Non-2's complement.");

/*
 *  Insure the range of unsigned is 2x that of positive signed
 *  Only ever seen one once with the widest unsigned and signed type with same max
 */
static_assert(SCHAR_MAX == UCHAR_MAX/2 && SHRT_MAX == USHRT_MAX/2 &&
    INT_MAX == UINT_MAX/2 && LONG_MAX == ULONG_MAX/2 &&
    LLONG_MAX == ULLONG_MAX/2 && INTMAX_MAX == UINTMAX_MAX/2, 
        "Dinosaur"Dinosuar: narrowed unsigned.");

/*
 *  Insure char is sub-range of int
 *  When char values exceed int, makes for tough code using fgetc()
 */
static_assert(CHAR_MAX <= INT_MAX, "Dinosaur"Dinosuar: wide char");

/*
 *  Insure char is a power-2-octet
 *  I suspect many folks would prefer just CHAR_BIT == 8
 */
static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0, "Dinosaur: Uncommon byte width.");

/*
 *  Only binary FP
 */
static_assert(FLT_RADIX == 2, "Dinosaur"Dinosuar: Non binary FP");

/*
 *  Some light checking for pass-able FP types
 *  Certainly this is not a full IEEE check
 *  Tolerate float as double
 */
static_assert(sizeof(float)*CHAR_BIT == 32 || sizeof(float)*CHAR_BIT == 64,
    "Dinosaur"Dinosuar: Unusual float");
static_assert(sizeof(double)*CHAR_BIT == 64, "Dinosaur"Dinosuar: Unusual double");

/*
 *  Heavier IEEE checking
 */
static_assert(DBL_MAX_10_EXP == 308 && DBL_MAX_EXP == 1024 &&
    DBL_MIN_10_EXP == -307 && DBL_MIN_EXP == -1021 &&
    DBL_DIG == 15 && DBL_DECIMAL_DIG == 17 && DBL_MANT_DIG == 53,
    "Dinosaur"Dinosuar: Unusual double");

/*
 *  Insure uxxx_t range <= int
 *  Strange when unsigned helper types promote to int
 */
static_assert(INT_MAX < UINTPTR_MAX, "Unicorn: narrow uintptr_t");
static_assert(INT_MAX < SIZE_MAX, "Unicorn: narrow size_tt");

/*
 *  Insure xxx_t range >= int
 *  Also expect signed helper types at least int range
 */
static_assert(INT_MAX <= PTRDIFF_MAX, "Unicorn: narrow ptrdiff_t");
static_assert(INT_MAX <= INTPTR_MAX, "Unicorn: narrow intptr_");

/*
 *  Insure all integers are within `float` finite range
 */
// Works OK when uintmax_t lacks padding
static_assert(FLT_RADIX == 2 && sizeof(uintmax_t)*CHAR_BIT < FLT_MAX_EXP,
    "Unicorn: wide integer range");
// Better method
#define UNICODE_BW1(x) ((x) > 0x1u ? 2 : 1)
#define UNICODE_BW2(x) ((x) > 0x3u ? UNICODE_BW1((x)/0x4)+2 : UNICODE_BW1(x))
#define UNICODE_BW3(x) ((x) > 0xFu ? UNICODE_BW2((x)/0x10)+4 : UNICODE_BW2(x))
#define UNICODE_BW4(x) ((x) > 0xFFu ? UNICODE_BW3((x)/0x100)+8 : UNICODE_BW3(x))
#define UNICODE_BW5(x) ((x) > 0xFFFFu ? UNICODE_BW4((x)/0x10000)+16 : UNICODE_BW4(x))
#define UNICODE_BW6(x) ((x) > 0xFFFFFFFFu ? \
    UNICODE_BW5((x)/0x100000000)+32 : UNICODE_BW5(x))
#define UNICODE_BW(x) ((x) > 0xFFFFFFFFFFFFFFFFu ? \
    UNICODE_BW6((x)/0x100000000/0x100000000)+64 : UNICODE_BW6(x))
static_assert(FLT_RADIX == 2 && UNICODE_BW(UINTMAX_MAX) < FLT_MAX_EXP,
    "Unicorn: wide integer range");

/*
 *  Insure size_t range > int
 *  Strange code when a `size_t` object promotes to an `int`.
 */
static_assert(INT_MAX < SIZE_MAX, "Unicorn: narrow size_t");

/*
 *  Recommended practice 7.19 4
 */
static_assert(PTRDIFF_MAX <= LONG_MAX, "Unicorn: ptrdiff_t wider than long");
static_assert(SIZE_MAX <= ULONG_MAX, "Unicorn: size_t wider thna unsigned long");

/*
 *  Insure range of integers within float
 */
static_assert(FLT_RADIX == 2 && sizeof(uintmax_t)*CHAR_BIT < FLT_MAX_EXP,
    "Unicorn: wide integer range");

// Addition code could #undef the various UNICODE_BWn

#endif /* UNICORN_H_ */
/*
 * unicorn.h
 * Various tests to detect old and strange compilers.
 *
 *  Created on: Mar 8, 2019
 *      Author: chux
 */

#ifndef UNICORN_H_
#define UNICORN_H_

#include <assert.h>
#ifndef static_assert
  #define static_assert( e, m ) typedef char _brevit_static_assert[!!(e)]
#endif

#include <float.h>
#include <limits.h>
#include <stdint.h>

/*
 *  Insure 2's complement
 *  Could also check various int_leastN_t, int_fastN_t
 */
static_assert(SCHAR_MIN < -SCHAR_MAX && SHRT_MIN < -SHRT_MAX &&
    INT_MIN < -INT_MAX && LONG_MIN < -LONG_MAX &&
    LLONG_MIN < -LLONG_MAX && INTMAX_MIN < -INTMAX_MAX &&
    INTPTR_MIN < -INTPTR_MAX && PTRDIFF_MIN < -PTRDIFF_MAX
    , "Dinosaur: Non-2's complement.");

/*
 *  Insure the range of unsigned is 2x that of positive signed
 *  Only ever seen one once with the widest unsigned and signed type with same max
 */
static_assert(SCHAR_MAX == UCHAR_MAX/2 && SHRT_MAX == USHRT_MAX/2 &&
    INT_MAX == UINT_MAX/2 && LONG_MAX == ULONG_MAX/2 &&
    LLONG_MAX == ULLONG_MAX/2 && INTMAX_MAX == UINTMAX_MAX/2, 
        "Dinosaur: narrowed unsigned.");

/*
 *  Insure char is sub-range of int
 *  When char values exceed int, makes for tough code using fgetc()
 */
static_assert(CHAR_MAX <= INT_MAX, "Dinosaur: wide char");

/*
 *  Insure char is a power-2-octet
 *  I suspect many folks would prefer just CHAR_BIT == 8
 */
static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0, "Dinosaur: Uncommon byte width.");

/*
 *  Only binary FP
 */
static_assert(FLT_RADIX == 2, "Dinosaur: Non binary FP");

/*
 *  Some light checking for pass-able FP types
 *  Certainly this is not a full IEEE check
 *  Tolerate float as double
 */
static_assert(sizeof(float)*CHAR_BIT == 32 || sizeof(float)*CHAR_BIT == 64,
    "Dinosaur: Unusual float");
static_assert(sizeof(double)*CHAR_BIT == 64, "Dinosaur: Unusual double");

/*
 *  Heavier IEEE checking
 */
static_assert(DBL_MAX_10_EXP == 308 && DBL_MAX_EXP == 1024 &&
    DBL_MIN_10_EXP == -307 && DBL_MIN_EXP == -1021 &&
    DBL_DIG == 15 && DBL_DECIMAL_DIG == 17 && DBL_MANT_DIG == 53,
    "Dinosaur: Unusual double");

/*
 *  Insure uxxx_t range <= int
 *  Strange when unsigned helper types promote to int
 */
static_assert(INT_MAX < UINTPTR_MAX, "Unicorn: narrow uintptr_t");
static_assert(INT_MAX < SIZE_MAX, "Unicorn: narrow size_tt");

/*
 *  Insure xxx_t range >= int
 *  Also expect signed helper types at least int range
 */
static_assert(INT_MAX <= PTRDIFF_MAX, "Unicorn: narrow ptrdiff_t");
static_assert(INT_MAX <= INTPTR_MAX, "Unicorn: narrow intptr_");

/*
 *  Insure all integers are within `float` finite range
 */
// Works OK when uintmax_t lacks padding
static_assert(FLT_RADIX == 2 && sizeof(uintmax_t)*CHAR_BIT < FLT_MAX_EXP,
    "Unicorn: wide integer range");
// Better method
#define UNICODE_BW1(x) ((x) > 0x1u ? 2 : 1)
#define UNICODE_BW2(x) ((x) > 0x3u ? UNICODE_BW1((x)/0x4)+2 : UNICODE_BW1(x))
#define UNICODE_BW3(x) ((x) > 0xFu ? UNICODE_BW2((x)/0x10)+4 : UNICODE_BW2(x))
#define UNICODE_BW4(x) ((x) > 0xFFu ? UNICODE_BW3((x)/0x100)+8 : UNICODE_BW3(x))
#define UNICODE_BW5(x) ((x) > 0xFFFFu ? UNICODE_BW4((x)/0x10000)+16 : UNICODE_BW4(x))
#define UNICODE_BW6(x) ((x) > 0xFFFFFFFFu ? \
    UNICODE_BW5((x)/0x100000000)+32 : UNICODE_BW5(x))
#define UNICODE_BW(x) ((x) > 0xFFFFFFFFFFFFFFFFu ? \
    UNICODE_BW6((x)/0x100000000/0x100000000)+64 : UNICODE_BW6(x))
static_assert(FLT_RADIX == 2 && UNICODE_BW(UINTMAX_MAX) < FLT_MAX_EXP,
    "Unicorn: wide integer range");

/*
 *  Insure size_t range > int
 *  Strange code when a `size_t` object promotes to an `int`.
 */
static_assert(INT_MAX < SIZE_MAX, "Unicorn: narrow size_t");

/*
 *  Recommended practice 7.19 4
 */
static_assert(PTRDIFF_MAX <= LONG_MAX, "Unicorn: ptrdiff_t wider than long");
static_assert(SIZE_MAX <= ULONG_MAX, "Unicorn: size_t wider thna unsigned long");

/*
 *  Insure range of integers within float
 */
static_assert(FLT_RADIX == 2 && sizeof(uintmax_t)*CHAR_BIT < FLT_MAX_EXP,
    "Unicorn: wide integer range");

// Addition code could #undef the various UNICODE_BWn

#endif /* UNICORN_H_ */
/*
 * unicorn.h
 * Various tests to detect old and strange compilers.
 *
 *  Created on: Mar 8, 2019
 *      Author: chux
 */

#ifndef UNICORN_H_
#define UNICORN_H_

#include <assert.h>
#ifndef static_assert
  #define static_assert( e, m ) typedef char _brevit_static_assert[!!(e)]
#endif

#include <float.h>
#include <limits.h>
#include <stdint.h>

/*
 *  Insure 2's complement
 *  Could also check various int_leastN_t, int_fastN_t
 */
static_assert(SCHAR_MIN < -SCHAR_MAX && SHRT_MIN < -SHRT_MAX &&
    INT_MIN < -INT_MAX && LONG_MIN < -LONG_MAX &&
    LLONG_MIN < -LLONG_MAX && INTMAX_MIN < -INTMAX_MAX &&
    INTPTR_MIN < -INTPTR_MAX && PTRDIFF_MIN < -PTRDIFF_MAX
    , "Dinosuar: Non-2's complement.");

/*
 *  Insure the range of unsigned is 2x that of positive signed
 *  Only ever seen one once with the widest unsigned and signed type with same max
 */
static_assert(SCHAR_MAX == UCHAR_MAX/2 && SHRT_MAX == USHRT_MAX/2 &&
    INT_MAX == UINT_MAX/2 && LONG_MAX == ULONG_MAX/2 &&
    LLONG_MAX == ULLONG_MAX/2 && INTMAX_MAX == UINTMAX_MAX/2, 
        "Dinosuar: narrowed unsigned.");

/*
 *  Insure char is sub-range of int
 *  When char values exceed int, makes for tough code using fgetc()
 */
static_assert(CHAR_MAX <= INT_MAX, "Dinosuar: wide char");

/*
 *  Insure char is a power-2-octet
 *  I suspect many folks would prefer just CHAR_BIT == 8
 */
static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0, "Dinosaur: Uncommon byte width.");

/*
 *  Only binary FP
 */
static_assert(FLT_RADIX == 2, "Dinosuar: Non binary FP");

/*
 *  Some light checking for pass-able FP types
 *  Certainly this is not a full IEEE check
 *  Tolerate float as double
 */
static_assert(sizeof(float)*CHAR_BIT == 32 || sizeof(float)*CHAR_BIT == 64,
    "Dinosuar: Unusual float");
static_assert(sizeof(double)*CHAR_BIT == 64, "Dinosuar: Unusual double");

/*
 *  Heavier IEEE checking
 */
static_assert(DBL_MAX_10_EXP == 308 && DBL_MAX_EXP == 1024 &&
    DBL_MIN_10_EXP == -307 && DBL_MIN_EXP == -1021 &&
    DBL_DIG == 15 && DBL_DECIMAL_DIG == 17 && DBL_MANT_DIG == 53,
    "Dinosuar: Unusual double");

/*
 *  Insure uxxx_t range <= int
 *  Strange when unsigned helper types promote to int
 */
static_assert(INT_MAX < UINTPTR_MAX, "Unicorn: narrow uintptr_t");
static_assert(INT_MAX < SIZE_MAX, "Unicorn: narrow size_tt");

/*
 *  Insure xxx_t range >= int
 *  Also expect signed helper types at least int range
 */
static_assert(INT_MAX <= PTRDIFF_MAX, "Unicorn: narrow ptrdiff_t");
static_assert(INT_MAX <= INTPTR_MAX, "Unicorn: narrow intptr_");

/*
 *  Insure all integers are within `float` finite range
 */
// Works OK when uintmax_t lacks padding
static_assert(FLT_RADIX == 2 && sizeof(uintmax_t)*CHAR_BIT < FLT_MAX_EXP,
    "Unicorn: wide integer range");
// Better method
#define UNICODE_BW1(x) ((x) > 0x1u ? 2 : 1)
#define UNICODE_BW2(x) ((x) > 0x3u ? UNICODE_BW1((x)/0x4)+2 : UNICODE_BW1(x))
#define UNICODE_BW3(x) ((x) > 0xFu ? UNICODE_BW2((x)/0x10)+4 : UNICODE_BW2(x))
#define UNICODE_BW4(x) ((x) > 0xFFu ? UNICODE_BW3((x)/0x100)+8 : UNICODE_BW3(x))
#define UNICODE_BW5(x) ((x) > 0xFFFFu ? UNICODE_BW4((x)/0x10000)+16 : UNICODE_BW4(x))
#define UNICODE_BW6(x) ((x) > 0xFFFFFFFFu ? \
    UNICODE_BW5((x)/0x100000000)+32 : UNICODE_BW5(x))
#define UNICODE_BW(x) ((x) > 0xFFFFFFFFFFFFFFFFu ? \
    UNICODE_BW6((x)/0x100000000/0x100000000)+64 : UNICODE_BW6(x))
static_assert(FLT_RADIX == 2 && UNICODE_BW(UINTMAX_MAX) < FLT_MAX_EXP,
    "Unicorn: wide integer range");

/*
 *  Insure size_t range > int
 *  Strange code when a `size_t` object promotes to an `int`.
 */
static_assert(INT_MAX < SIZE_MAX, "Unicorn: narrow size_t");

/*
 *  Recommended practice 7.19 4
 */
static_assert(PTRDIFF_MAX <= LONG_MAX, "Unicorn: ptrdiff_t wider than long");
static_assert(SIZE_MAX <= ULONG_MAX, "Unicorn: size_t wider thna unsigned long");

/*
 *  Insure range of integers within float
 */
static_assert(FLT_RADIX == 2 && sizeof(uintmax_t)*CHAR_BIT < FLT_MAX_EXP,
    "Unicorn: wide integer range");

// Addition code could #undef the various UNICODE_BWn

#endif /* UNICORN_H_ */
Rollback to Revision 3
Source Link
Mast
  • 13.9k
  • 12
  • 57
  • 128
Loading
Use real superscripts
Source Link
Toby Speight
  • 88.5k
  • 14
  • 104
  • 327
Loading
Tweeted twitter.com/StackCodeReview/status/1104532461017616384
edited title
Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading