Tim Streater said:
I'm porting a couple of C apps to OS X and I notice that one of the apps
has the following in a .h file:
#define UBYTE unsigned char // 8-bit unsigned
#define BYTE signed char // 8-bit signed
#define UWORD unsigned short // 16-bit unsigned
#define WORD short // 16-bit signed
#define ULONG unsigned int // 32-bit unsigned
#define LONG int // 32-bit signed
#define ULONG64 unsigned long long // 64-bit unsigned
#define LONG64 long long // 64-bit signed
The other seems to use the naked type definitions such as short,
unsigned long, etc.
Now, as both these apps have been ported at least once before, and while
I've made the first of them apparently work, I can imagine there may be
problems due to word lengths and types. Is there an easy way determine
the numbers of bits the compiler allocates to each data type?
The program below may yield the information you're seeking.
/* Find widths and maximum values of regular integer types. */
#include <limits.h>
#define TYPE_WIDTH(T) ((unsigned) IMAX_BITS( TYPE_MAX(T) ) + ((T)-1 < 1))
#define TYPE_MAX(T) ((T) TM_WT_( T, UNSIGNED_MAX_MAX ))
#if __STDC_VERSION__ > 199900L
#include <stdint.h>
#include <inttypes.h>
#if defined UINTMAX_MAX
#define UNSIGNED_MAX_MAX UINTMAX_MAX
#define UMAX_FORMAT PRIuMAX
typedef uintmax_t unsigned_max;
#elif defined ULLONG_MAX
#define UNSIGNED_MAX_MAX ULLONG_MAX
#define UMAX_FORMAT "llu"
typedef unsigned long long unsigned_max;
#else
#define UNSIGNED_MAX_MAX ULONG_MAX
#define UMAX_FORMAT "lu"
typedef unsigned long unsigned_max;
#endif
#elif defined ULLONG_MAX
#define UNSIGNED_MAX_MAX ULLONG_MAX
#define UMAX_FORMAT "llu"
typedef unsigned long long unsigned_max;
#else
#define UNSIGNED_MAX_MAX ULONG_MAX
#define UMAX_FORMAT "lu"
typedef unsigned long unsigned_max;
#endif
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
#if IMAX_BITS(UNSIGNED_MAX_MAX) > 16384
#error number of bits in UNSIGNED_MAX_MAX unreasonably high
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 8192
#define TM_WT_(T,v) TM_D_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 4096
#define TM_WT_(T,v) TM_C_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 2048
#define TM_WT_(T,v) TM_B_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 1024
#define TM_WT_(T,v) TM_A_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 512
#define TM_WT_(T,v) TM_9_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 256
#define TM_WT_(T,v) TM_8_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 128
#define TM_WT_(T,v) TM_7_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 64
#define TM_WT_(T,v) TM_6_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 32
#define TM_WT_(T,v) TM_5_(T,v)
#elif IMAX_BITS(UNSIGNED_MAX_MAX) > 16
#define TM_WT_(T,v) TM_4_(T,v)
#else
#error number of bits in UNSIGNED_MAX_MAX impossibly low
#endif
#define TM_D_(T,v) ( TM_OK(T,v>>8191) ? TM_C_(T,v) : TM_C_(T,(v>>8192)) )
#define TM_C_(T,v) ( TM_OK(T,v>>4095) ? TM_B_(T,v) : TM_B_(T,(v>>4096)) )
#define TM_B_(T,v) ( TM_OK(T,v>>2047) ? TM_A_(T,v) : TM_A_(T,(v>>2048)) )
#define TM_A_(T,v) ( TM_OK(T,v>>1023) ? TM_9_(T,v) : TM_9_(T,(v>>1024)) )
#define TM_9_(T,v) ( TM_OK(T,v>> 511) ? TM_8_(T,v) : TM_8_(T,(v>> 512)) )
#define TM_8_(T,v) ( TM_OK(T,v>> 255) ? TM_7_(T,v) : TM_7_(T,(v>> 256)) )
#define TM_7_(T,v) ( TM_OK(T,v>> 127) ? TM_6_(T,v) : TM_6_(T,(v>> 128)) )
#define TM_6_(T,v) ( TM_OK(T,v>> 63) ? TM_5_(T,v) : TM_5_(T,(v>> 64)) )
#define TM_5_(T,v) ( TM_OK(T,v>> 31) ? TM_4_(T,v) : TM_4_(T,(v>> 32)) )
#define TM_4_(T,v) ( TM_OK(T,v>> 15) ? TM_3_(T,v) : TM_3_(T,(v>> 16)) )
#define TM_3_(T,v) ( TM_OK(T,v>> 7) ? TM_2_(T,v) : TM_2_(T,(v>> 8)) )
#define TM_2_(T,v) ( TM_OK(T,v>> 3) ? TM_1_(T,v) : TM_1_(T,(v>> 4)) )
#define TM_1_(T,v) ( TM_OK(T,v>> 1) ? TM_0_(T,v) : TM_0_(T,(v>> 2)) )
#define TM_0_(T,v) ( TM_OK(T,v ) ? v : v>> 1 )
#define TM_OK(T,v) ( (T)(v) > 0 && (T)(v) == (v) )
#include <stddef.h>
#include <stdio.h>
char test_array[ TYPE_MAX(char) ];
#define PRINT_WIDTH(T) \
printf( "Width of %20s is %5u\n", #T, TYPE_WIDTH(T) )
#define PRINT_MAX(T) \
printf( "Maximum value of %20s is %25" UMAX_FORMAT "\n", \
#T, (unsigned_max) TYPE_MAX(T) \
)
int
main(){
#if __STDC_VERSION__ > 199900L
PRINT_WIDTH(_Bool);
printf( "\n" );
#endif
PRINT_WIDTH(char);
PRINT_WIDTH(signed char);
PRINT_WIDTH(unsigned char);
printf( "\n" );
PRINT_WIDTH(short);
PRINT_WIDTH(signed short);
PRINT_WIDTH(unsigned short);
printf( "\n" );
PRINT_WIDTH(int);
PRINT_WIDTH(signed int);
PRINT_WIDTH(unsigned int);
printf( "\n" );
PRINT_WIDTH(long);
PRINT_WIDTH(signed long);
PRINT_WIDTH(unsigned long);
printf( "\n" );
PRINT_WIDTH(ptrdiff_t);
PRINT_WIDTH(size_t);
printf( "\n" );
#if __STDC_VERSION__ > 199900L || defined ULLONG_MAX
PRINT_WIDTH(long long);
PRINT_WIDTH(signed long long);
PRINT_WIDTH(unsigned long long);
printf( "\n" );
#endif
#if __STDC_VERSION__ > 199900L
PRINT_MAX(_Bool);
printf( "\n" );
#endif
PRINT_MAX(char);
PRINT_MAX(signed char);
PRINT_MAX(unsigned char);
printf( "\n" );
PRINT_MAX(short);
PRINT_MAX(signed short);
PRINT_MAX(unsigned short);
printf( "\n" );
PRINT_MAX(int);
PRINT_MAX(signed int);
PRINT_MAX(unsigned int);
printf( "\n" );
PRINT_MAX(long);
PRINT_MAX(signed long);
PRINT_MAX(unsigned long);
printf( "\n" );
PRINT_MAX(ptrdiff_t);
PRINT_MAX(size_t);
printf( "\n" );
#if __STDC_VERSION__ > 199900L || defined ULLONG_MAX
PRINT_MAX(long long);
PRINT_MAX(signed long long);
PRINT_MAX(unsigned long long);
printf( "\n" );
#endif
printf( "\n" );
printf( " sizeof test_array is %25" UMAX_FORMAT "\n",
(unsigned_max) sizeof test_array
);
printf( "\n" );
printf( " Value of UNSIGNED_MAX_MAX is %25" UMAX_FORMAT "\n",
(unsigned_max) UNSIGNED_MAX_MAX
);
printf( "\n" );
printf( " UMAX_FORMAT is %25s\n", UMAX_FORMAT );
printf( "\n" );
return 0;
}