Velocity Reviews > Weary of using -1 for max unsigned values

# Weary of using -1 for max unsigned values

CBFalconer
Guest
Posts: n/a

 10-27-2007
Dan Henry wrote:
> Martin Wells <(E-Mail Removed)> wrote:
>
>
>> I commonly use the likes of -1 for max unsigned values, ...

>
> -1 does not convert to the maximum unsigned value for one's
> complement representation.

Yes it does. This is a portable technique.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Charlie Gordon
Guest
Posts: n/a

 10-27-2007
"James Kuyper" <(E-Mail Removed)> a écrit dans le message de news:
wsJUi.447\$TO4.392@trnddc07...
> Dan Henry wrote:
>> On Thu, 25 Oct 2007 10:48:01 -0700, Martin Wells <(E-Mail Removed)>
>> wrote:
>>
>>> I commonly use the likes of -1 for max unsigned values, ...

>>
>> -1 does not convert to the maximum unsigned value for one's complement
>> representation.

>
> The representation of the signed integer type is irrelevant. It's the
> value that gets converted, not it's representation. The relevant rule is
> given in 6.3.1.3p2:
>
> "Otherwise, if the new type is unsigned, the value is converted by
> repeatedly adding or subtracting one more than the maximum value that can
> be represented in the new type until the value is in the range of the new
> type."
>
> In the case of -1, that means adding "one more than the maximum value"
> to -1, which gives you exactly the maximum value.

The likely consequence of this is that casting a int to unsigned on one of
those obsolete museum pieces emits code, possibly even a test and one or two
jumps.

One's complement is nothing to worry about.

--
Chqrlie.

Charlie Gordon
Guest
Posts: n/a

 10-27-2007
"Martin Wells" <(E-Mail Removed)> a écrit dans le message de news:
(E-Mail Removed) m...
> Chqrlie:
>
>> #define MWELLS_CMP(val, x) \
>> (((unsigned long long)(long long)(val) & \
>> (-1ULL >> ((sizeof(1ULL) - sizeof(x)) * CHAR_BIT)) == (x))
>>
>> Use it as:
>>
>> if (MWELLS_CMP(-6, x)) ...

>
>
> (You've got an extra open parenthesis at the very start)

Actually, there is a missing parenthesis after CHAR_BIT.

#define MWELLS_CMP(val, x) \
(((unsigned long long)(long long)(val) & \
(-1ULL >> ((sizeof(1ULL) - sizeof(x)) * CHAR_BIT))) == (x))

> I'm gonna think out loud here and see if I understand it
>
> (
> (unsigned long long)(long long)(val)
>
> Here you take val, convert it to a long long, then to an unsigned long
> long. Why don't you go straight to an unsigned long long?

no good reason, let's simplify:

#define MWELLS_CMP(val, x) \
(((unsigned long long)(val) & \
(-1ULL >> ((sizeof(1ULL) - sizeof(x)) * CHAR_BIT))) == (x))

> &
> (
> -1ULL >>
> ( (sizeof(1ULL) - sizeof(x)) * CHAR_BIT )
> )
>
> == (x)
> )
>
> Now you take the byte difference between unsigned long long and the
> expression, and multiply it by CHAR_BIT to get the bit difference. You
> shift the max value of unsigned long long to the right by this bit
> difference.

Correct: this produces the value UCHAR_MAX, UINT_MAX, ULONG_MAX or
ULLONG_MAX depending on the type of x.

> You then compare this value to X, yielding an int value of
> either 1 or 0, and you then bitwiseAND this with the previous value
> above. I haven't fully thought it through but it seems you might have
> an error above as regards operands and operator precedence.

With the missing parenthesis, the value produced in the step above is used
to mask off the high bits of val sign extended to (at least) 64 bits.

> Anyway,
> two flaws that stick out are:
>
> 1) Unsigned types can have padding, so sizeof isn't reliable for the
> amount of value representational bits.

2's complement) architectures, but the commitee forgot simple macros telling
the gory details, it is non trivial to derive INT_BIT from INT_MAX in a
macro, but can be done.

> 2) Use of unsigned long long is specific to C99. If we're gonna bother
> with C99, then we'd be better off to go with int_max_t or whatever
> it's called. As for C89, we can only go with unsigned long... but the
> implemenation could provide a bigger type.

obviously, you can tailor the macro for strict c89 and c99:

#define MWELLS_CMP89(val, x) \
(((unsigned long)(val) & \
(-1UL >> ((sizeof(1UL) - sizeof(x)) * CHAR_BIT))) == (x))

#define MWELLS_CMP99(val, x) \
(((uintmax_t)(val) & \
((uintmax_t)-1 >> ((sizeof(uintmax_t) - sizeof(x)) * CHAR_BIT))) ==
(x))

Enjoy!

--
Chqrlie.

Dan Henry
Guest
Posts: n/a

 10-28-2007
On Sat, 27 Oct 2007 16:13:16 GMT, James Kuyper
<(E-Mail Removed)> wrote:

>Dan Henry wrote:
>> On Thu, 25 Oct 2007 10:48:01 -0700, Martin Wells <(E-Mail Removed)>
>> wrote:
>>
>>> I commonly use the likes of -1 for max unsigned values, ...

>>
>> -1 does not convert to the maximum unsigned value for one's complement
>> representation.

>
>The representation of the signed integer type is irrelevant.

I was in a bit pattern frame of mind, but am feeling better now.

--
Dan Henry