D
D Yuniskis
Hi,
I frequently have to write code that must run on a variety
of different platforms (portability). Many of these are
legacy systems with tools that are no longer supported.
(i.e., I often am working in a C89 context).
Almost always, the code needs data types to be tweaked to
best fit the characteristics of the target machine (embedded
system work so resources are almost always scarce). This is
an area that is ripe for error!
What I try to do is rely on the preprocessor and limits.h to
have the preprocessor "pick" the appropriate data types for me.
Often, this works. But, when it doesn't work, it doesn't
work at all!
For example, I might look for the smallest type that can
support a particular datum by doing something like:
#if (MY_MAX_VALUE < UCHAR_MAX)
typedef unsigned char mytype_t;
#elif (MY_MAX_VALUE < USHRT_MAX)
typedef unsigned short mytype_t;
#elif (MY_MAX_VALUE < ULONG_MAX)
....
#endif
Similarly, I may use type limits to determine just how
big I can let things get in my algorithms (e.g., "if
I use an unsigned long and I need to represent a maximum
value of MAX_VALUE then how many bits can I get to the
right of the binary point if I scale the datum accordingly?")
The problem I have is when MY_MAX_VALUE -- or, some
arithmetic expression which effectively becomes MY_MAX_VALUE
exceeds the capabilities of a 32 bit int (for older compilers).
For example, extend the first example to include:
....
#elif (MY_MAX_VALUE < ULLONG_MAX)
typedef unsigned long long mytype_t;
#else
#error "Unable to represent MY_MAX_VALUE with standard data types"
#endif
If, for example, MY_MAX_VALUE won't fit in a ULONG, then it
is too big for "older" preprocessors to handle predictably.
(Note that I can always #define MAX_ULLONG to be 0 to ensure
this conditional is never active. But, that doesn't say
how the preprocessor will behave when computing the value
MY_MAX_VALUE when said value exceeds a "long").
[Note that MY_MAX_VALUE is often an expression that might
evaluate to one of these "too large for preprocessor" values]
I currently work around this by having a dependency in my makefile
that causes an executable to run which "does the math" and makes
the choice for me. But, this presents other problems as it relies
on there being a compiler for the *host* available at build time
(I do mainly cross builds).
Any suggestions on alternative techniques to getting this support
at compile time (run-time checks are "too late" :> )
Thanks!
--don
I frequently have to write code that must run on a variety
of different platforms (portability). Many of these are
legacy systems with tools that are no longer supported.
(i.e., I often am working in a C89 context).
Almost always, the code needs data types to be tweaked to
best fit the characteristics of the target machine (embedded
system work so resources are almost always scarce). This is
an area that is ripe for error!
What I try to do is rely on the preprocessor and limits.h to
have the preprocessor "pick" the appropriate data types for me.
Often, this works. But, when it doesn't work, it doesn't
work at all!
For example, I might look for the smallest type that can
support a particular datum by doing something like:
#if (MY_MAX_VALUE < UCHAR_MAX)
typedef unsigned char mytype_t;
#elif (MY_MAX_VALUE < USHRT_MAX)
typedef unsigned short mytype_t;
#elif (MY_MAX_VALUE < ULONG_MAX)
....
#endif
Similarly, I may use type limits to determine just how
big I can let things get in my algorithms (e.g., "if
I use an unsigned long and I need to represent a maximum
value of MAX_VALUE then how many bits can I get to the
right of the binary point if I scale the datum accordingly?")
The problem I have is when MY_MAX_VALUE -- or, some
arithmetic expression which effectively becomes MY_MAX_VALUE
exceeds the capabilities of a 32 bit int (for older compilers).
For example, extend the first example to include:
....
#elif (MY_MAX_VALUE < ULLONG_MAX)
typedef unsigned long long mytype_t;
#else
#error "Unable to represent MY_MAX_VALUE with standard data types"
#endif
If, for example, MY_MAX_VALUE won't fit in a ULONG, then it
is too big for "older" preprocessors to handle predictably.
(Note that I can always #define MAX_ULLONG to be 0 to ensure
this conditional is never active. But, that doesn't say
how the preprocessor will behave when computing the value
MY_MAX_VALUE when said value exceeds a "long").
[Note that MY_MAX_VALUE is often an expression that might
evaluate to one of these "too large for preprocessor" values]
I currently work around this by having a dependency in my makefile
that causes an executable to run which "does the math" and makes
the choice for me. But, this presents other problems as it relies
on there being a compiler for the *host* available at build time
(I do mainly cross builds).
Any suggestions on alternative techniques to getting this support
at compile time (run-time checks are "too late" :> )
Thanks!
--don