Detecting unicorn and dinosaur compilersDoing #ifdef DEBUG and #define func() right?Processes and semaphores in CDetecting a combination of characters from inputStyle and Suggestions for K&R2 1-18Calculate the average score of groups and each student, CDetecting arithmetic overflow in C with NASMGenerate String with Random Consonants and Vowels in CFactorials, loops, break and professional codeCalculate g.c.d and l.c.m. in CAxiomatic Lisp interpreter in C

What features enable the Su-25 Frogfoot to operate with such a wide variety of fuels?

Pre-mixing cryogenic fuels and using only one fuel tank

Why does a simple loop result in ASYNC_NETWORK_IO waits?

What are the balance implications behind making invisible things auto-hide?

Why is it that I can sometimes guess the next note?

Mimic lecturing on blackboard, facing audience

Do we have to expect a queue for the shuttle from Watford Junction to Harry Potter Studio?

Yosemite Fire Rings - What to Expect?

What is Cash Advance APR?

Quasinilpotent , non-compact operators

User Story breakdown - Technical Task + User Feature

How should I address a possible mistake to co-authors in a submitted paper

Multiplicative persistence

What are some good ways to treat frozen vegetables such that they behave like fresh vegetables when stir frying them?

Temporarily disable WLAN internet access for children, but allow it for adults

How to create table with 2D function values?

Is there a way to get `mathscr' with lower case letters in pdfLaTeX?

How much character growth crosses the line into breaking the character

How can I write humor as character trait?

Is there a RAID 0 Equivalent for RAM?

PTIJ: Haman's bad computer

How can I avoid dust and bubbles when installing window film?

Example of factorization in a polynomial ring which is not an UFD

The IT department bottlenecks progress, how should I handle this?



Detecting unicorn and dinosaur compilers


Doing #ifdef DEBUG and #define func() right?Processes and semaphores in CDetecting a combination of characters from inputStyle and Suggestions for K&R2 1-18Calculate the average score of groups and each student, CDetecting arithmetic overflow in C with NASMGenerate String with Random Consonants and Vowels in CFactorials, loops, break and professional codeCalculate g.c.d and l.c.m. in CAxiomatic Lisp interpreter in C













12












$begingroup$


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.



Yet if code might not handle such cases as non-2's complement, it is prudent to detect and fail such compilations today.



Rather than just look for that one kind of dinosaur¹, below is C code that looks for various unicorns² and dinosaurs. Certainly some tests are more useful than others.



Review goal:



  • Please report any dinosaur¹ and unicorns² compilers found by this code.


  • Review how well this code would successfully flag true passé compilers and not report new innovative ones (e.g. 128-bit intmax_t.)


  • Suggest any additional or refined tests.


  • Pre-C11 compilers that lack static_assert may readily need a better #define static_assert ... than this code. Better alternatives are appreciated, but not a main goal of this post.


Note: I am not trying to rate strict adherence to IEEE_754 and the like.




/*
* 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_ */


Test driver



#include "unicorn.h"
#include <stdio.h>

int main(void)
printf("Hello World!n");
return 0;




¹ C is very flexible, yet some features applied to compilers simply no longer in use for over 10 years. For compilers that used out-of-favor features (non-2's complement, non-power-of-2 bit width "bytes", non-binary floating-point, etc.) I'll call dinosaurs.



² C is very flexible for new platform/compilers too. Some of these potential and theoretical compliers could employ very unusual features. I'll call these compilers unicorns. Should one appear, I rather have code fail to compile than compile with errant functioning code.










share|improve this question











$endgroup$











  • $begingroup$
    Silly me - did not use an ASCII test yet....
    $endgroup$
    – chux
    Mar 9 at 19:27











  • $begingroup$
    Are you sure you don't want to ensure that unsigned char is a sub-range of int instead? To wit, EOF being distinct is useful.
    $endgroup$
    – Deduplicator
    Mar 9 at 20:49










  • $begingroup$
    @Deduplicator Yes, for fgetc() , UCHAR_MAX <= INT_MAX is better and CHAR_MAX <= INT_MAX insufficient. Suggest forming an answer with that.
    $endgroup$
    – chux
    Mar 9 at 20:55







  • 2




    $begingroup$
    Serious question - how frequently do you run into these types of compilers? I think this is a cool idea! But honestly, I would never need it, as even doing cross-platform stuff, we usually know ahead-of-time which compilers we'll use, and none would have features this obscure. I'm always curious to learn a little about the things I don't run into myself.
    $endgroup$
    – user1118321
    Mar 9 at 23:12










  • $begingroup$
    @user1118321 "know ahead-of-time which compilers we'll use, and none would have features this obscure" --> that is what this file is for: to help make that assessment. Consider it a like a spell checker. I certainly do not come across unicorns even sporadically, yet an automated review could help. Additional tests could help detect near-unicorns.
    $endgroup$
    – chux
    Mar 10 at 22:05
















12












$begingroup$


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.



Yet if code might not handle such cases as non-2's complement, it is prudent to detect and fail such compilations today.



Rather than just look for that one kind of dinosaur¹, below is C code that looks for various unicorns² and dinosaurs. Certainly some tests are more useful than others.



Review goal:



  • Please report any dinosaur¹ and unicorns² compilers found by this code.


  • Review how well this code would successfully flag true passé compilers and not report new innovative ones (e.g. 128-bit intmax_t.)


  • Suggest any additional or refined tests.


  • Pre-C11 compilers that lack static_assert may readily need a better #define static_assert ... than this code. Better alternatives are appreciated, but not a main goal of this post.


Note: I am not trying to rate strict adherence to IEEE_754 and the like.




/*
* 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_ */


Test driver



#include "unicorn.h"
#include <stdio.h>

int main(void)
printf("Hello World!n");
return 0;




¹ C is very flexible, yet some features applied to compilers simply no longer in use for over 10 years. For compilers that used out-of-favor features (non-2's complement, non-power-of-2 bit width "bytes", non-binary floating-point, etc.) I'll call dinosaurs.



² C is very flexible for new platform/compilers too. Some of these potential and theoretical compliers could employ very unusual features. I'll call these compilers unicorns. Should one appear, I rather have code fail to compile than compile with errant functioning code.










share|improve this question











$endgroup$











  • $begingroup$
    Silly me - did not use an ASCII test yet....
    $endgroup$
    – chux
    Mar 9 at 19:27











  • $begingroup$
    Are you sure you don't want to ensure that unsigned char is a sub-range of int instead? To wit, EOF being distinct is useful.
    $endgroup$
    – Deduplicator
    Mar 9 at 20:49










  • $begingroup$
    @Deduplicator Yes, for fgetc() , UCHAR_MAX <= INT_MAX is better and CHAR_MAX <= INT_MAX insufficient. Suggest forming an answer with that.
    $endgroup$
    – chux
    Mar 9 at 20:55







  • 2




    $begingroup$
    Serious question - how frequently do you run into these types of compilers? I think this is a cool idea! But honestly, I would never need it, as even doing cross-platform stuff, we usually know ahead-of-time which compilers we'll use, and none would have features this obscure. I'm always curious to learn a little about the things I don't run into myself.
    $endgroup$
    – user1118321
    Mar 9 at 23:12










  • $begingroup$
    @user1118321 "know ahead-of-time which compilers we'll use, and none would have features this obscure" --> that is what this file is for: to help make that assessment. Consider it a like a spell checker. I certainly do not come across unicorns even sporadically, yet an automated review could help. Additional tests could help detect near-unicorns.
    $endgroup$
    – chux
    Mar 10 at 22:05














12












12








12


2



$begingroup$


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.



Yet if code might not handle such cases as non-2's complement, it is prudent to detect and fail such compilations today.



Rather than just look for that one kind of dinosaur¹, below is C code that looks for various unicorns² and dinosaurs. Certainly some tests are more useful than others.



Review goal:



  • Please report any dinosaur¹ and unicorns² compilers found by this code.


  • Review how well this code would successfully flag true passé compilers and not report new innovative ones (e.g. 128-bit intmax_t.)


  • Suggest any additional or refined tests.


  • Pre-C11 compilers that lack static_assert may readily need a better #define static_assert ... than this code. Better alternatives are appreciated, but not a main goal of this post.


Note: I am not trying to rate strict adherence to IEEE_754 and the like.




/*
* 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_ */


Test driver



#include "unicorn.h"
#include <stdio.h>

int main(void)
printf("Hello World!n");
return 0;




¹ C is very flexible, yet some features applied to compilers simply no longer in use for over 10 years. For compilers that used out-of-favor features (non-2's complement, non-power-of-2 bit width "bytes", non-binary floating-point, etc.) I'll call dinosaurs.



² C is very flexible for new platform/compilers too. Some of these potential and theoretical compliers could employ very unusual features. I'll call these compilers unicorns. Should one appear, I rather have code fail to compile than compile with errant functioning code.










share|improve this question











$endgroup$




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.



Yet if code might not handle such cases as non-2's complement, it is prudent to detect and fail such compilations today.



Rather than just look for that one kind of dinosaur¹, below is C code that looks for various unicorns² and dinosaurs. Certainly some tests are more useful than others.



Review goal:



  • Please report any dinosaur¹ and unicorns² compilers found by this code.


  • Review how well this code would successfully flag true passé compilers and not report new innovative ones (e.g. 128-bit intmax_t.)


  • Suggest any additional or refined tests.


  • Pre-C11 compilers that lack static_assert may readily need a better #define static_assert ... than this code. Better alternatives are appreciated, but not a main goal of this post.


Note: I am not trying to rate strict adherence to IEEE_754 and the like.




/*
* 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_ */


Test driver



#include "unicorn.h"
#include <stdio.h>

int main(void)
printf("Hello World!n");
return 0;




¹ C is very flexible, yet some features applied to compilers simply no longer in use for over 10 years. For compilers that used out-of-favor features (non-2's complement, non-power-of-2 bit width "bytes", non-binary floating-point, etc.) I'll call dinosaurs.



² C is very flexible for new platform/compilers too. Some of these potential and theoretical compliers could employ very unusual features. I'll call these compilers unicorns. Should one appear, I rather have code fail to compile than compile with errant functioning code.







c






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 11 at 10:22









Toby Speight

26.5k742118




26.5k742118










asked Mar 9 at 19:13









chuxchux

13.5k21345




13.5k21345











  • $begingroup$
    Silly me - did not use an ASCII test yet....
    $endgroup$
    – chux
    Mar 9 at 19:27











  • $begingroup$
    Are you sure you don't want to ensure that unsigned char is a sub-range of int instead? To wit, EOF being distinct is useful.
    $endgroup$
    – Deduplicator
    Mar 9 at 20:49










  • $begingroup$
    @Deduplicator Yes, for fgetc() , UCHAR_MAX <= INT_MAX is better and CHAR_MAX <= INT_MAX insufficient. Suggest forming an answer with that.
    $endgroup$
    – chux
    Mar 9 at 20:55







  • 2




    $begingroup$
    Serious question - how frequently do you run into these types of compilers? I think this is a cool idea! But honestly, I would never need it, as even doing cross-platform stuff, we usually know ahead-of-time which compilers we'll use, and none would have features this obscure. I'm always curious to learn a little about the things I don't run into myself.
    $endgroup$
    – user1118321
    Mar 9 at 23:12










  • $begingroup$
    @user1118321 "know ahead-of-time which compilers we'll use, and none would have features this obscure" --> that is what this file is for: to help make that assessment. Consider it a like a spell checker. I certainly do not come across unicorns even sporadically, yet an automated review could help. Additional tests could help detect near-unicorns.
    $endgroup$
    – chux
    Mar 10 at 22:05

















  • $begingroup$
    Silly me - did not use an ASCII test yet....
    $endgroup$
    – chux
    Mar 9 at 19:27











  • $begingroup$
    Are you sure you don't want to ensure that unsigned char is a sub-range of int instead? To wit, EOF being distinct is useful.
    $endgroup$
    – Deduplicator
    Mar 9 at 20:49










  • $begingroup$
    @Deduplicator Yes, for fgetc() , UCHAR_MAX <= INT_MAX is better and CHAR_MAX <= INT_MAX insufficient. Suggest forming an answer with that.
    $endgroup$
    – chux
    Mar 9 at 20:55







  • 2




    $begingroup$
    Serious question - how frequently do you run into these types of compilers? I think this is a cool idea! But honestly, I would never need it, as even doing cross-platform stuff, we usually know ahead-of-time which compilers we'll use, and none would have features this obscure. I'm always curious to learn a little about the things I don't run into myself.
    $endgroup$
    – user1118321
    Mar 9 at 23:12










  • $begingroup$
    @user1118321 "know ahead-of-time which compilers we'll use, and none would have features this obscure" --> that is what this file is for: to help make that assessment. Consider it a like a spell checker. I certainly do not come across unicorns even sporadically, yet an automated review could help. Additional tests could help detect near-unicorns.
    $endgroup$
    – chux
    Mar 10 at 22:05
















$begingroup$
Silly me - did not use an ASCII test yet....
$endgroup$
– chux
Mar 9 at 19:27





$begingroup$
Silly me - did not use an ASCII test yet....
$endgroup$
– chux
Mar 9 at 19:27













$begingroup$
Are you sure you don't want to ensure that unsigned char is a sub-range of int instead? To wit, EOF being distinct is useful.
$endgroup$
– Deduplicator
Mar 9 at 20:49




$begingroup$
Are you sure you don't want to ensure that unsigned char is a sub-range of int instead? To wit, EOF being distinct is useful.
$endgroup$
– Deduplicator
Mar 9 at 20:49












$begingroup$
@Deduplicator Yes, for fgetc() , UCHAR_MAX <= INT_MAX is better and CHAR_MAX <= INT_MAX insufficient. Suggest forming an answer with that.
$endgroup$
– chux
Mar 9 at 20:55





$begingroup$
@Deduplicator Yes, for fgetc() , UCHAR_MAX <= INT_MAX is better and CHAR_MAX <= INT_MAX insufficient. Suggest forming an answer with that.
$endgroup$
– chux
Mar 9 at 20:55





2




2




$begingroup$
Serious question - how frequently do you run into these types of compilers? I think this is a cool idea! But honestly, I would never need it, as even doing cross-platform stuff, we usually know ahead-of-time which compilers we'll use, and none would have features this obscure. I'm always curious to learn a little about the things I don't run into myself.
$endgroup$
– user1118321
Mar 9 at 23:12




$begingroup$
Serious question - how frequently do you run into these types of compilers? I think this is a cool idea! But honestly, I would never need it, as even doing cross-platform stuff, we usually know ahead-of-time which compilers we'll use, and none would have features this obscure. I'm always curious to learn a little about the things I don't run into myself.
$endgroup$
– user1118321
Mar 9 at 23:12












$begingroup$
@user1118321 "know ahead-of-time which compilers we'll use, and none would have features this obscure" --> that is what this file is for: to help make that assessment. Consider it a like a spell checker. I certainly do not come across unicorns even sporadically, yet an automated review could help. Additional tests could help detect near-unicorns.
$endgroup$
– chux
Mar 10 at 22:05





$begingroup$
@user1118321 "know ahead-of-time which compilers we'll use, and none would have features this obscure" --> that is what this file is for: to help make that assessment. Consider it a like a spell checker. I certainly do not come across unicorns even sporadically, yet an automated review could help. Additional tests could help detect near-unicorns.
$endgroup$
– chux
Mar 10 at 22:05











3 Answers
3






active

oldest

votes


















3












$begingroup$

I'm appalled! What kind of code are you writing that's so inflexible it needs all these tests? ;-p



Seriously, it ought to be possible to enable only the tests that the including code needs, perhaps by predefining macros that declare its non-portabilities:



#ifdef REQUIRE_BINARY_FP
static_assert(FLT_RADIX == 2, "Dinosuar: Non binary FP");
#endif


(to pick a simple example)




On an extremely minor note, in the comments you've consistently written "insure" where you evidently mean "ensure".




Additional tests to consider:



  • I've seen code that breaks if 'z' - 'a' != 25 and/or 'Z' - 'A' != 25.

  • Some code requires the existence of exact-width integer types such as uint32_t, which are not available on all platforms (it's possible this is covered by the power-of-two byte-width test, but I can't prove it).

  • Perhaps some code requires long double to be bigger (in precision and/or range) than double?





share|improve this answer











$endgroup$




















    3












    $begingroup$

    • I think that static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0 can be pretty safely replaced by CHAR_BIT==8. There are various old DSP compilers that would fail the test, but they are indeed dinosaur systems.



    • stdint.h and constants like SIZE_MAX, PTRDIFF_MAX were added in C99. So by using such macros/constants, you'll essentially cause all C90 compilers to fail compilation.



      Are C90 compilers dinosaurs per your definition? If not, then maybe
      do some checks if __STDC_VERSION__ is defined and if so what
      version. Because most of the exotic ones are likely to follow C90.







    share|improve this answer









    $endgroup$




















      0












      $begingroup$

      In addition to fine answers @Toby Speight, @Lundin and a related FP question, came up with additional idea/detail.



      Spelling*



      "Dinosuar" --> "Dinosaur".



      ASCII or not*



      Could use a lengthy test of the execution character set C11 §5.2.1 3



      A to Z
      a to z
      0 to 9
      ! " # % & ’ ( ) * + , - . / : ; < = > ? [ ] ^ _ ~
      space character,
      and control characters representing horizontal tab, vertical tab, and form feed.
      some way of indicating the end of each line of text


      Note that the 3 "$@"`, ASCII 127 and various control characters are not mentioned above.



       static_assert(
      'A' == 65 && 'B' == 66 && 'C' == 67 && 'D' == 68 && 'E' == 69 && 'F' == 70
      && 'G' == 71 && 'H' == 72 && 'I' == 73 && 'J' == 74 && 'K' == 75
      && 'L' == 76 && 'M' == 77 && 'N' == 78 && 'O' == 79 && 'P' == 80
      && 'Q' == 81 && 'R' == 82 && 'S' == 83 && 'T' == 84 && 'U' == 85
      && 'V' == 86 && 'W' == 87 && 'X' == 88 && 'Y' == 89 && 'Z' == 90,
      "Dinosaur: not ASCII A-Z");
      static_assert(
      'a' == 97 && 'b' == 98 && 'c' == 99 && 'd' == 100 && 'e' == 101
      && 'f' == 102 && 'g' == 103 && 'h' == 104 && 'i' == 105 && 'j' == 106
      && 'k' == 107 && 'l' == 108 && 'm' == 109 && 'n' == 110 && 'o' == 111
      && 'p' == 112 && 'q' == 113 && 'r' == 114 && 's' == 115 && 't' == 116
      && 'u' == 117 && 'v' == 118 && 'w' == 119 && 'x' == 120 && 'y' == 121
      && 'z' == 122, "Dinosaur: not ASCII a-z");
      static_assert('0' == 48, "Dinosaur: not ASCII 0-9"); // 1-9 follow 0 by spec.
      static_assert(
      '!' == 33 && '"' == 34 && '#' == 35 && '%' == 37 && '&' == 38
      && ''' == 39 && '(' == 40 && ')' == 41 && '*' == 42 && '+' == 43
      && ',' == 44 && '-' == 45 && '.' == 46 && '/' == 47 && ':' == 58
      && ';' == 59 && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63
      && '[' == 91 && '\' == 92 && ']' == 93 && '^' == 94 && '_' == 95
      && '' == 123 && '' == 125 && '~',
      "Dinosaur: not ASCII punct");
      static_assert(
      ' ' == 32 && 't' == 9 && 'v' == 11 && 'f' == 12 && 'n' == 10,
      "Dinosaur: not ASCII space, ctrl");
      static_assert('a' == 7 && 'b' == 8 && 'r' == 13,
      "Dinosaur: not ASCII spaces");
      // Not 100% confident safe to do the following test
      static_assert('$' == 36 && '@' == 64 && '`' == 96,
      "Dinosaur: not ASCII special");





      share|improve this answer









      $endgroup$












        Your Answer





        StackExchange.ifUsing("editor", function ()
        return StackExchange.using("mathjaxEditing", function ()
        StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
        StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
        );
        );
        , "mathjax-editing");

        StackExchange.ifUsing("editor", function ()
        StackExchange.using("externalEditor", function ()
        StackExchange.using("snippets", function ()
        StackExchange.snippets.init();
        );
        );
        , "code-snippets");

        StackExchange.ready(function()
        var channelOptions =
        tags: "".split(" "),
        id: "196"
        ;
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function()
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled)
        StackExchange.using("snippets", function()
        createEditor();
        );

        else
        createEditor();

        );

        function createEditor()
        StackExchange.prepareEditor(
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: false,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        imageUploader:
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        ,
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        );



        );













        draft saved

        draft discarded


















        StackExchange.ready(
        function ()
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215113%2fdetecting-unicorn-and-dinosaur-compilers%23new-answer', 'question_page');

        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        3












        $begingroup$

        I'm appalled! What kind of code are you writing that's so inflexible it needs all these tests? ;-p



        Seriously, it ought to be possible to enable only the tests that the including code needs, perhaps by predefining macros that declare its non-portabilities:



        #ifdef REQUIRE_BINARY_FP
        static_assert(FLT_RADIX == 2, "Dinosuar: Non binary FP");
        #endif


        (to pick a simple example)




        On an extremely minor note, in the comments you've consistently written "insure" where you evidently mean "ensure".




        Additional tests to consider:



        • I've seen code that breaks if 'z' - 'a' != 25 and/or 'Z' - 'A' != 25.

        • Some code requires the existence of exact-width integer types such as uint32_t, which are not available on all platforms (it's possible this is covered by the power-of-two byte-width test, but I can't prove it).

        • Perhaps some code requires long double to be bigger (in precision and/or range) than double?





        share|improve this answer











        $endgroup$

















          3












          $begingroup$

          I'm appalled! What kind of code are you writing that's so inflexible it needs all these tests? ;-p



          Seriously, it ought to be possible to enable only the tests that the including code needs, perhaps by predefining macros that declare its non-portabilities:



          #ifdef REQUIRE_BINARY_FP
          static_assert(FLT_RADIX == 2, "Dinosuar: Non binary FP");
          #endif


          (to pick a simple example)




          On an extremely minor note, in the comments you've consistently written "insure" where you evidently mean "ensure".




          Additional tests to consider:



          • I've seen code that breaks if 'z' - 'a' != 25 and/or 'Z' - 'A' != 25.

          • Some code requires the existence of exact-width integer types such as uint32_t, which are not available on all platforms (it's possible this is covered by the power-of-two byte-width test, but I can't prove it).

          • Perhaps some code requires long double to be bigger (in precision and/or range) than double?





          share|improve this answer











          $endgroup$















            3












            3








            3





            $begingroup$

            I'm appalled! What kind of code are you writing that's so inflexible it needs all these tests? ;-p



            Seriously, it ought to be possible to enable only the tests that the including code needs, perhaps by predefining macros that declare its non-portabilities:



            #ifdef REQUIRE_BINARY_FP
            static_assert(FLT_RADIX == 2, "Dinosuar: Non binary FP");
            #endif


            (to pick a simple example)




            On an extremely minor note, in the comments you've consistently written "insure" where you evidently mean "ensure".




            Additional tests to consider:



            • I've seen code that breaks if 'z' - 'a' != 25 and/or 'Z' - 'A' != 25.

            • Some code requires the existence of exact-width integer types such as uint32_t, which are not available on all platforms (it's possible this is covered by the power-of-two byte-width test, but I can't prove it).

            • Perhaps some code requires long double to be bigger (in precision and/or range) than double?





            share|improve this answer











            $endgroup$



            I'm appalled! What kind of code are you writing that's so inflexible it needs all these tests? ;-p



            Seriously, it ought to be possible to enable only the tests that the including code needs, perhaps by predefining macros that declare its non-portabilities:



            #ifdef REQUIRE_BINARY_FP
            static_assert(FLT_RADIX == 2, "Dinosuar: Non binary FP");
            #endif


            (to pick a simple example)




            On an extremely minor note, in the comments you've consistently written "insure" where you evidently mean "ensure".




            Additional tests to consider:



            • I've seen code that breaks if 'z' - 'a' != 25 and/or 'Z' - 'A' != 25.

            • Some code requires the existence of exact-width integer types such as uint32_t, which are not available on all platforms (it's possible this is covered by the power-of-two byte-width test, but I can't prove it).

            • Perhaps some code requires long double to be bigger (in precision and/or range) than double?






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Mar 11 at 12:43

























            answered Mar 11 at 11:07









            Toby SpeightToby Speight

            26.5k742118




            26.5k742118























                3












                $begingroup$

                • I think that static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0 can be pretty safely replaced by CHAR_BIT==8. There are various old DSP compilers that would fail the test, but they are indeed dinosaur systems.



                • stdint.h and constants like SIZE_MAX, PTRDIFF_MAX were added in C99. So by using such macros/constants, you'll essentially cause all C90 compilers to fail compilation.



                  Are C90 compilers dinosaurs per your definition? If not, then maybe
                  do some checks if __STDC_VERSION__ is defined and if so what
                  version. Because most of the exotic ones are likely to follow C90.







                share|improve this answer









                $endgroup$

















                  3












                  $begingroup$

                  • I think that static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0 can be pretty safely replaced by CHAR_BIT==8. There are various old DSP compilers that would fail the test, but they are indeed dinosaur systems.



                  • stdint.h and constants like SIZE_MAX, PTRDIFF_MAX were added in C99. So by using such macros/constants, you'll essentially cause all C90 compilers to fail compilation.



                    Are C90 compilers dinosaurs per your definition? If not, then maybe
                    do some checks if __STDC_VERSION__ is defined and if so what
                    version. Because most of the exotic ones are likely to follow C90.







                  share|improve this answer









                  $endgroup$















                    3












                    3








                    3





                    $begingroup$

                    • I think that static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0 can be pretty safely replaced by CHAR_BIT==8. There are various old DSP compilers that would fail the test, but they are indeed dinosaur systems.



                    • stdint.h and constants like SIZE_MAX, PTRDIFF_MAX were added in C99. So by using such macros/constants, you'll essentially cause all C90 compilers to fail compilation.



                      Are C90 compilers dinosaurs per your definition? If not, then maybe
                      do some checks if __STDC_VERSION__ is defined and if so what
                      version. Because most of the exotic ones are likely to follow C90.







                    share|improve this answer









                    $endgroup$



                    • I think that static_assert((CHAR_BIT & (CHAR_BIT - 1)) == 0 can be pretty safely replaced by CHAR_BIT==8. There are various old DSP compilers that would fail the test, but they are indeed dinosaur systems.



                    • stdint.h and constants like SIZE_MAX, PTRDIFF_MAX were added in C99. So by using such macros/constants, you'll essentially cause all C90 compilers to fail compilation.



                      Are C90 compilers dinosaurs per your definition? If not, then maybe
                      do some checks if __STDC_VERSION__ is defined and if so what
                      version. Because most of the exotic ones are likely to follow C90.








                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Mar 11 at 15:41









                    LundinLundin

                    1,837823




                    1,837823





















                        0












                        $begingroup$

                        In addition to fine answers @Toby Speight, @Lundin and a related FP question, came up with additional idea/detail.



                        Spelling*



                        "Dinosuar" --> "Dinosaur".



                        ASCII or not*



                        Could use a lengthy test of the execution character set C11 §5.2.1 3



                        A to Z
                        a to z
                        0 to 9
                        ! " # % & ’ ( ) * + , - . / : ; < = > ? [ ] ^ _ ~
                        space character,
                        and control characters representing horizontal tab, vertical tab, and form feed.
                        some way of indicating the end of each line of text


                        Note that the 3 "$@"`, ASCII 127 and various control characters are not mentioned above.



                         static_assert(
                        'A' == 65 && 'B' == 66 && 'C' == 67 && 'D' == 68 && 'E' == 69 && 'F' == 70
                        && 'G' == 71 && 'H' == 72 && 'I' == 73 && 'J' == 74 && 'K' == 75
                        && 'L' == 76 && 'M' == 77 && 'N' == 78 && 'O' == 79 && 'P' == 80
                        && 'Q' == 81 && 'R' == 82 && 'S' == 83 && 'T' == 84 && 'U' == 85
                        && 'V' == 86 && 'W' == 87 && 'X' == 88 && 'Y' == 89 && 'Z' == 90,
                        "Dinosaur: not ASCII A-Z");
                        static_assert(
                        'a' == 97 && 'b' == 98 && 'c' == 99 && 'd' == 100 && 'e' == 101
                        && 'f' == 102 && 'g' == 103 && 'h' == 104 && 'i' == 105 && 'j' == 106
                        && 'k' == 107 && 'l' == 108 && 'm' == 109 && 'n' == 110 && 'o' == 111
                        && 'p' == 112 && 'q' == 113 && 'r' == 114 && 's' == 115 && 't' == 116
                        && 'u' == 117 && 'v' == 118 && 'w' == 119 && 'x' == 120 && 'y' == 121
                        && 'z' == 122, "Dinosaur: not ASCII a-z");
                        static_assert('0' == 48, "Dinosaur: not ASCII 0-9"); // 1-9 follow 0 by spec.
                        static_assert(
                        '!' == 33 && '"' == 34 && '#' == 35 && '%' == 37 && '&' == 38
                        && ''' == 39 && '(' == 40 && ')' == 41 && '*' == 42 && '+' == 43
                        && ',' == 44 && '-' == 45 && '.' == 46 && '/' == 47 && ':' == 58
                        && ';' == 59 && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63
                        && '[' == 91 && '\' == 92 && ']' == 93 && '^' == 94 && '_' == 95
                        && '' == 123 && '' == 125 && '~',
                        "Dinosaur: not ASCII punct");
                        static_assert(
                        ' ' == 32 && 't' == 9 && 'v' == 11 && 'f' == 12 && 'n' == 10,
                        "Dinosaur: not ASCII space, ctrl");
                        static_assert('a' == 7 && 'b' == 8 && 'r' == 13,
                        "Dinosaur: not ASCII spaces");
                        // Not 100% confident safe to do the following test
                        static_assert('$' == 36 && '@' == 64 && '`' == 96,
                        "Dinosaur: not ASCII special");





                        share|improve this answer









                        $endgroup$

















                          0












                          $begingroup$

                          In addition to fine answers @Toby Speight, @Lundin and a related FP question, came up with additional idea/detail.



                          Spelling*



                          "Dinosuar" --> "Dinosaur".



                          ASCII or not*



                          Could use a lengthy test of the execution character set C11 §5.2.1 3



                          A to Z
                          a to z
                          0 to 9
                          ! " # % & ’ ( ) * + , - . / : ; < = > ? [ ] ^ _ ~
                          space character,
                          and control characters representing horizontal tab, vertical tab, and form feed.
                          some way of indicating the end of each line of text


                          Note that the 3 "$@"`, ASCII 127 and various control characters are not mentioned above.



                           static_assert(
                          'A' == 65 && 'B' == 66 && 'C' == 67 && 'D' == 68 && 'E' == 69 && 'F' == 70
                          && 'G' == 71 && 'H' == 72 && 'I' == 73 && 'J' == 74 && 'K' == 75
                          && 'L' == 76 && 'M' == 77 && 'N' == 78 && 'O' == 79 && 'P' == 80
                          && 'Q' == 81 && 'R' == 82 && 'S' == 83 && 'T' == 84 && 'U' == 85
                          && 'V' == 86 && 'W' == 87 && 'X' == 88 && 'Y' == 89 && 'Z' == 90,
                          "Dinosaur: not ASCII A-Z");
                          static_assert(
                          'a' == 97 && 'b' == 98 && 'c' == 99 && 'd' == 100 && 'e' == 101
                          && 'f' == 102 && 'g' == 103 && 'h' == 104 && 'i' == 105 && 'j' == 106
                          && 'k' == 107 && 'l' == 108 && 'm' == 109 && 'n' == 110 && 'o' == 111
                          && 'p' == 112 && 'q' == 113 && 'r' == 114 && 's' == 115 && 't' == 116
                          && 'u' == 117 && 'v' == 118 && 'w' == 119 && 'x' == 120 && 'y' == 121
                          && 'z' == 122, "Dinosaur: not ASCII a-z");
                          static_assert('0' == 48, "Dinosaur: not ASCII 0-9"); // 1-9 follow 0 by spec.
                          static_assert(
                          '!' == 33 && '"' == 34 && '#' == 35 && '%' == 37 && '&' == 38
                          && ''' == 39 && '(' == 40 && ')' == 41 && '*' == 42 && '+' == 43
                          && ',' == 44 && '-' == 45 && '.' == 46 && '/' == 47 && ':' == 58
                          && ';' == 59 && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63
                          && '[' == 91 && '\' == 92 && ']' == 93 && '^' == 94 && '_' == 95
                          && '' == 123 && '' == 125 && '~',
                          "Dinosaur: not ASCII punct");
                          static_assert(
                          ' ' == 32 && 't' == 9 && 'v' == 11 && 'f' == 12 && 'n' == 10,
                          "Dinosaur: not ASCII space, ctrl");
                          static_assert('a' == 7 && 'b' == 8 && 'r' == 13,
                          "Dinosaur: not ASCII spaces");
                          // Not 100% confident safe to do the following test
                          static_assert('$' == 36 && '@' == 64 && '`' == 96,
                          "Dinosaur: not ASCII special");





                          share|improve this answer









                          $endgroup$















                            0












                            0








                            0





                            $begingroup$

                            In addition to fine answers @Toby Speight, @Lundin and a related FP question, came up with additional idea/detail.



                            Spelling*



                            "Dinosuar" --> "Dinosaur".



                            ASCII or not*



                            Could use a lengthy test of the execution character set C11 §5.2.1 3



                            A to Z
                            a to z
                            0 to 9
                            ! " # % & ’ ( ) * + , - . / : ; < = > ? [ ] ^ _ ~
                            space character,
                            and control characters representing horizontal tab, vertical tab, and form feed.
                            some way of indicating the end of each line of text


                            Note that the 3 "$@"`, ASCII 127 and various control characters are not mentioned above.



                             static_assert(
                            'A' == 65 && 'B' == 66 && 'C' == 67 && 'D' == 68 && 'E' == 69 && 'F' == 70
                            && 'G' == 71 && 'H' == 72 && 'I' == 73 && 'J' == 74 && 'K' == 75
                            && 'L' == 76 && 'M' == 77 && 'N' == 78 && 'O' == 79 && 'P' == 80
                            && 'Q' == 81 && 'R' == 82 && 'S' == 83 && 'T' == 84 && 'U' == 85
                            && 'V' == 86 && 'W' == 87 && 'X' == 88 && 'Y' == 89 && 'Z' == 90,
                            "Dinosaur: not ASCII A-Z");
                            static_assert(
                            'a' == 97 && 'b' == 98 && 'c' == 99 && 'd' == 100 && 'e' == 101
                            && 'f' == 102 && 'g' == 103 && 'h' == 104 && 'i' == 105 && 'j' == 106
                            && 'k' == 107 && 'l' == 108 && 'm' == 109 && 'n' == 110 && 'o' == 111
                            && 'p' == 112 && 'q' == 113 && 'r' == 114 && 's' == 115 && 't' == 116
                            && 'u' == 117 && 'v' == 118 && 'w' == 119 && 'x' == 120 && 'y' == 121
                            && 'z' == 122, "Dinosaur: not ASCII a-z");
                            static_assert('0' == 48, "Dinosaur: not ASCII 0-9"); // 1-9 follow 0 by spec.
                            static_assert(
                            '!' == 33 && '"' == 34 && '#' == 35 && '%' == 37 && '&' == 38
                            && ''' == 39 && '(' == 40 && ')' == 41 && '*' == 42 && '+' == 43
                            && ',' == 44 && '-' == 45 && '.' == 46 && '/' == 47 && ':' == 58
                            && ';' == 59 && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63
                            && '[' == 91 && '\' == 92 && ']' == 93 && '^' == 94 && '_' == 95
                            && '' == 123 && '' == 125 && '~',
                            "Dinosaur: not ASCII punct");
                            static_assert(
                            ' ' == 32 && 't' == 9 && 'v' == 11 && 'f' == 12 && 'n' == 10,
                            "Dinosaur: not ASCII space, ctrl");
                            static_assert('a' == 7 && 'b' == 8 && 'r' == 13,
                            "Dinosaur: not ASCII spaces");
                            // Not 100% confident safe to do the following test
                            static_assert('$' == 36 && '@' == 64 && '`' == 96,
                            "Dinosaur: not ASCII special");





                            share|improve this answer









                            $endgroup$



                            In addition to fine answers @Toby Speight, @Lundin and a related FP question, came up with additional idea/detail.



                            Spelling*



                            "Dinosuar" --> "Dinosaur".



                            ASCII or not*



                            Could use a lengthy test of the execution character set C11 §5.2.1 3



                            A to Z
                            a to z
                            0 to 9
                            ! " # % & ’ ( ) * + , - . / : ; < = > ? [ ] ^ _ ~
                            space character,
                            and control characters representing horizontal tab, vertical tab, and form feed.
                            some way of indicating the end of each line of text


                            Note that the 3 "$@"`, ASCII 127 and various control characters are not mentioned above.



                             static_assert(
                            'A' == 65 && 'B' == 66 && 'C' == 67 && 'D' == 68 && 'E' == 69 && 'F' == 70
                            && 'G' == 71 && 'H' == 72 && 'I' == 73 && 'J' == 74 && 'K' == 75
                            && 'L' == 76 && 'M' == 77 && 'N' == 78 && 'O' == 79 && 'P' == 80
                            && 'Q' == 81 && 'R' == 82 && 'S' == 83 && 'T' == 84 && 'U' == 85
                            && 'V' == 86 && 'W' == 87 && 'X' == 88 && 'Y' == 89 && 'Z' == 90,
                            "Dinosaur: not ASCII A-Z");
                            static_assert(
                            'a' == 97 && 'b' == 98 && 'c' == 99 && 'd' == 100 && 'e' == 101
                            && 'f' == 102 && 'g' == 103 && 'h' == 104 && 'i' == 105 && 'j' == 106
                            && 'k' == 107 && 'l' == 108 && 'm' == 109 && 'n' == 110 && 'o' == 111
                            && 'p' == 112 && 'q' == 113 && 'r' == 114 && 's' == 115 && 't' == 116
                            && 'u' == 117 && 'v' == 118 && 'w' == 119 && 'x' == 120 && 'y' == 121
                            && 'z' == 122, "Dinosaur: not ASCII a-z");
                            static_assert('0' == 48, "Dinosaur: not ASCII 0-9"); // 1-9 follow 0 by spec.
                            static_assert(
                            '!' == 33 && '"' == 34 && '#' == 35 && '%' == 37 && '&' == 38
                            && ''' == 39 && '(' == 40 && ')' == 41 && '*' == 42 && '+' == 43
                            && ',' == 44 && '-' == 45 && '.' == 46 && '/' == 47 && ':' == 58
                            && ';' == 59 && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63
                            && '[' == 91 && '\' == 92 && ']' == 93 && '^' == 94 && '_' == 95
                            && '' == 123 && '' == 125 && '~',
                            "Dinosaur: not ASCII punct");
                            static_assert(
                            ' ' == 32 && 't' == 9 && 'v' == 11 && 'f' == 12 && 'n' == 10,
                            "Dinosaur: not ASCII space, ctrl");
                            static_assert('a' == 7 && 'b' == 8 && 'r' == 13,
                            "Dinosaur: not ASCII spaces");
                            // Not 100% confident safe to do the following test
                            static_assert('$' == 36 && '@' == 64 && '`' == 96,
                            "Dinosaur: not ASCII special");






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 14 mins ago









                            chuxchux

                            13.5k21345




                            13.5k21345



























                                draft saved

                                draft discarded
















































                                Thanks for contributing an answer to Code Review Stack Exchange!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid


                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.

                                Use MathJax to format equations. MathJax reference.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215113%2fdetecting-unicorn-and-dinosaur-compilers%23new-answer', 'question_page');

                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                瀋陽號驅逐艦 目录 接收與服役 配置反潛直升機 武進三型性能升級 歷史 除役 參考資料 外部連結 导航菜单Taiwan Air Power海疆老兵-陽字號驅逐艦沿革World Navies Today: Taiwan (Republic of China)DD-839 USS POWER

                                Memorizing the KeyboardThe Norwegian Foreman''If the B…''The Consonant EaterThe Cherry TreeElle Rend Le Coeur Plus AmoureuxFill in the blanks with the number in wordsState of the UnionFind the missing elementsCircuit DiagramWhat's the name of the game show?

                                名間水力發電廠 目录 沿革 設施 鄰近設施 註釋 外部連結 导航菜单23°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.7113923°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.71139計畫概要原始内容臺灣第一座BOT 模式開發的水力發電廠-名間水力電廠名間水力發電廠 水利署首件BOT案原始内容《小檔案》名間電廠 首座BOT水力發電廠原始内容名間電廠BOT - 經濟部水利署中區水資源局