After going through the logic again:
iter # i byte structure
1 1 0 00000001
2 2 0 00000010
3 3 0 00000100
4 4 0 00001000
5 5 0 00010000
6 6 0 00100000
7 7 0 01000000
8 8 0 10000000
9 1 1 00000001 00000000
10 2 1 00000010 00000000
11 3 1 00000100 00000000
12 4 1 00001000 00000000
13 5 1 00010000 00000000
14 6 1 00100000 00000000
15 7 1 01000000 00000000
16 8 1 10000000 00000000
17 1 2 00000001 00000000 00000000
Byte should be initialized to 1.
template <class T>
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;
}
> -----Original Message-----
> From: Martin Sebor [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, March 05, 2008 5:19 PM
> To: [email protected]
> Subject: Re: [PATCH] STDCXX-423
>
> Scott Zhong wrote:
> >
> >> -----Original Message-----
> >> From: Martin Sebor [mailto:[EMAIL PROTECTED]
> >> Sent: Wednesday, February 20, 2008 12:26 PM
> >> To: [email protected]
> >> Subject: Re: [PATCH] STDCXX-423
> >>
> >> Scott Zhong wrote:
> >> [...]
> >>>>> As I write this, I realize that the my function,
> >>> compute_byte_size(),
> >>>>> can be optimized to shift one bit to the next byte boundary.
> >>>> I don't think we need to (or should) worry about optimizing
config
> >>>> tests. What we might want to do is use the template parameter in
> >>>> the signature of the function for non-conforming compilers that
> >>>> have trouble with these types of things.
> >>> Sorry I meant to say that its more of a code fix than
optimization.
> >>> Sizeof() returns the number of bytes so the function should check
> > each
> >>> byte instead of each bit.
> >> But not all bits of every byte need to contribute to the value
> >> representation of the object. IIUC, there can be 4 byte ints
> >> (i.e., sizeof(int) == 4) with 29 bits for the value, 1 bit for
> >> the sign, and 2 bits of padding.
> >>
> >
> > I had overlooked that fact, thank you for reminding me.
> >
> >>>>> template <class T>
> >>>>> unsigned compute_byte_size()
> >>>>> {
> >>>>> T max = T (one);
> >>>>> unsigned byte = 0;
> >>>>> for (; T (max * 128) > max; max *= 128) {
> >>>> FWIW, for signed T the expression T(max * 128) > max has
undefined
> >>>> behavior in the presence of overflow. We've seen at least two (if
> >>>> not three) compilers exploit this presumably in some aggressive
> >>>> optimizations (see, for example, STDCXX-482). Since most (all?)
> >>>> hardware simply wraps around in the presence of overflow we just
> >>>> need to prevent the compiler optimization here.
> >>> Would the volatile keyword in front of "max" be sufficient here?
> >> It might help, but I'm not sure it's guaranteed to. All it usually
> >> does is make the compiler generate code that reloads the value of
> >> the object from memory into a register on each access. The stage
> >> I'm concerned with takes place before code generation based on what
> >> the compiler can prove about the program. For all signed x, the
> >> compiler is free to assume that in (x * N) > x, the subexpression
> >> (x * N) doesn't overflow and thus (x * N) is always guaranteed to
> >> be greater than x (for N > 0). To prevent it from making such an
> >> assumption we need to rewrite the expression like so: (x * N) > y
> >> while initializing x and y to the same value in such a way that
> >> the compiler cannot prove that (x == y) holds.
> >>
> >
> > Would this suffice?
>
> This doesn't seem correct, not just because of the typo but because
> it returns 3 for T = int (assuming one == 1). Even if it was correct
> I'm not sure a smart optimizer couldn't make some assumptions about
> the dependency between current and max (they are both modified using
> exactly the same expression) that would cause the code to misbehave.
>
> Martin
>
> >
> > template <class T>
> > unsigned compute_byte_size()
> > {
> > T max = T (one);
> > T current = T (one);
> > unsigned byte = 0;
> > for (int I = 1; T (current * 2) > max; current *= 2, max *= 2,
i++)
> > {
> > if (i > 8 ) {byte++; i = 1; }
> > }
> > return byte;
> > }
> >
> >
> >> Martin
> >