Scott Zhong wrote:
>> -----Original Message-----
>> From: Martin Sebor [mailto:sebor@roguewave.com]
>> Sent: Thursday, March 13, 2008 12:32 PM
>> To: dev@stdcxx.apache.org
>> Subject: RE: [PATCH] STDCXX-423
>>
>>
>> Okay, so this function seems to correctly compute the number of bytes
>> in the value representation of the object. Remind me, where do we need
>> it in the rest of LIMITS.cpp again? I.e., what does the patch look
>> like?
>>
>> Thanks
>> Martin
>>
>
> The patch looks like the following; it replaces SIZEOF macro on int
> types with CALC_SIZEOF macro. The CALC_SIZEOF macro expends to
> compute_byte_size function.
That's what I thought. I'm afraid I don't think this is correct.
The value of a sizeof expression must be the size of the operand
expressed as (n X CHAR_BIT), and that's what the test computes.
The problem noted in the issue is not with the sizeof operator or
the _RWSTD_XXX_SIZE macros but rather with the exact-width integer
types such as int32_t, and the assumption made in the test that
integer types for which sizeof returns 1, 2, 4, or 8, respectively,
have no padding bits.
For example, the code here:
http://fisheye6.cenqua.com/browse/stdcxx/trunk/etc/config/src/LIMITS.cpp?r=611451#l531
531 if (32 == char_bits * sizeof (int) && !(bits & 4)) {
532 bits |= 4;
533 printf ("#define _RWSTD_INT32_T int\n");
534 printf ("#define _RWSTD_UINT32_T unsigned int\n");
535 }
will incorrectly define int32_t to int when sizeof(int) == 4 holds even
when int has 1 or more padding bits.
I assume you're familiar with the C99 spec for exact-width integer types
but just for reference:
7.18.1.1 Exact-width integer types
-1- The typedef name intN_t designates a signed integer type with
width N, no padding bits, and a two’s complement representation.
Thus, int8_t denotes a signed integer type with a width of
exactly 8 bits.
-2- The typedef name uintN_t designates an unsigned integer type
with width N. Thus, uint24_t denotes an unsigned integer type
with a width of exactly 24 bits.
-3- These types are optional. However, if an implementation provides
integer types with widths of 8, 16, 32, or 64 bits, it shall
define the corresponding typedef names.
What we need to do to solve the exceedingly hypothetical problem noted
in STDCXX-423 is compute the number of bits in the value representation
of integer types with widths of 8, 16, 32, and 64 bits, compare the
results with number of bits in their object representation and only
if the two match define the corresponding exact-width typedefs.
Martin
>
> --- LIMITS.cpp (revision 624452)
> +++ LIMITS.cpp (working copy)
> @@ -223,13 +223,27 @@
> return bits;
> }
>
> +template
> +unsigned compute_byte_size()
> +{
> + T max = T (one);
> + T current = T(one);
> + unsigned byte = 1;
> + for (int i = 1; T (current * 2) > max; current *=2, max *= 2, i++)
> {
> + if (i > 8) { byte++; i=1; }
> + }
> + return byte;
> +}
>
> +
> // used to compute the size of a pointer to a member function struct
> EmptyStruct { };
>
>
> // to silence printf() format comaptibility warnings
> #define SIZEOF(T) unsigned (sizeof (T))
> +
> +// to not include possible bit padding
> +#define CALC_SIZEOF(T) compute_byte_size()
>
>
> int main ()
> @@ -243,17 +257,17 @@
>
> #ifndef _RWSTD_NO_BOOL
> printf ("#define _RWSTD_BOOL_SIZE %2u /* sizeof (bool) */\n",
> - SIZEOF (bool));
> + CALC_SIZEOF (bool));
> #endif // _RWSTD_NO_BOOL
>
> printf ("#define _RWSTD_CHAR_SIZE %2u /* sizeof (char) */\n",
> - SIZEOF (char));
> + CALC_SIZEOF (char));
> printf ("#define _RWSTD_SHRT_SIZE %2u /* sizeof (short) */\n",
> - SIZEOF (short));
> + CALC_SIZEOF (short));
> printf ("#define _RWSTD_INT_SIZE %2u /* sizeof (int) */\n",
> - SIZEOF (int));
> + CALC_SIZEOF (int));
> printf ("#define _RWSTD_LONG_SIZE %2u /* sizeof (long) */\n",
> - SIZEOF (long));
> + CALC_SIZEOF (long));
>
> printf ("#define _RWSTD_FLT_SIZE %2u /* sizeof (float) */\n",
> SIZEOF (float));
> @@ -319,7 +333,7 @@
>
> # define LLong long long
>
> - printf ("#define _RWSTD_LLONG_SIZE %2u\n", SIZEOF (LLong));
> + printf ("#define _RWSTD_LLONG_SIZE %2u\n", CALC_SIZEOF (LLong));
>
> const char llong_name[] = "long long";
>
> @@ -332,7 +346,7 @@
>
> # define LLong __int64
>
> - printf ("#define _RWSTD_LLONG_SIZE %2u\n", SIZEOF (LLong));
> + printf ("#define _RWSTD_LLONG_SIZE %2u\n", CALC_SIZEOF (LLong));
>
> const char llong_name[] = "__int64";
>
> @@ -352,7 +366,7 @@
> #ifndef _RWSTD_NO_WCHAR_T
>
> printf ("#define _RWSTD_WCHAR_SIZE %2u /* sizeof (wchar_t) */\n",
> - SIZEOF (wchar_t));
> + CALC_SIZEOF (wchar_t));
>
> const char *suffix = "U";
> if ((wchar_t)~0 < (wchar_t)0)
>
>
>