[Python-Dev] Deprecation warning on integer shifts and such

Guido van Rossum guido@python.org
Tue, 13 Aug 2002 16:29:09 -0400


> >> If we switch to "k" for integers in the range -2**-31..2**31-1 that
> >> would not be too much work, as a lot of the code is generated (I would
> >> take the quick and dirty approach of using k for all my integers). Only
> >> the hand-written code would have to be massaged by hand.
> >
> > Glad, that's my preferred choice too.  But note that in Python 2.4 and
> > beyond, 'k' will only accept positive inputs, so you'll really have to
> > find a way to mark your signed integer arguments up differently.
> 
> Huh??! Now you've confused me. If "k" means "32 bit mask", why would it 
> be changed in 2.4 not to accept negative values? "-1" is a perfectly 
> normal way to specify "0xffffffff" in C usage...

Hm, in Python I'd hope that people would write 0xffffffff if they want
32 one bits -- -1L has an infinite number of one bits, and on 64-bit
systems, -1 has 64 one-bits instead of 32.  Most masks are formed by
taking a small positive constant (e.g. 1 or 0xff) and shifting it
left.  In Python 2.4 that will always return a positive value.

But if you really don't like this, we could do something different --
'k' could simply give you the lower 32 bits of the value.  (Or the
lower sizeof(long)*8 bits???).

> > In 2.3 (and 2.2.2), I propose the following semantics for 'k': if the
> > argument is a Python int, a signed value within the range
> > [INT_MIN,INT_MAX] is required; if it is a Python long, a nonnegative
> > value in the range [0, 2*INT_MAX+1] is required.  These are the same
> > semantics that are currently used by struct.pack() for 'L', I found
> > out; I like these.
> 
> I don't see the point, really. Why not allow [INT_MIN, 2*INT_MAX+1]? If 
> the "k" specifier is especially meant for bit patterns why not have 
> semantics of "anything goes, unless we are absolutely sure it isn't 
> going to fit"?

In the end, I see two possibilities: lenient, taking the lower N bits,
or strict, requiring [0 .. 2**32-1].  The proposal I made above was an
intermediate move on the way to the strict approach (given the reality
that in 2.3, 1<<31 is negative).

> > We'll have to niggle about the C type corresponding to 'k'.  Should it
> > be 'int' or 'long'?  It may not matter for you, since you expect to be
> > running on 32-bit hardware forever; but it matters for other potential
> > users of 'k'.  We could also have both 'k' and 'K', where 'k' stores
> > into a C int and 'K' into a C long.
> 
> How about k1 for a byte, k2 for a short, k4 for a long and k8 for a long 
> long?

Hm, the format characters typically correspond to a specific C type.
We already have 'b' for unsigned char and 'B' for signed/unsigned
char, 'h' for unsigned short and 'H' for signed/unsigned short.  These
are unfortunately inconsistent with 'i' for signed int and 'l' for
signed long.

So I'd rather you pick a C type for 'k' (and a policy about range
checks).

> > I also propose to have a C API PyInt_AsUnsignedLong, which will
> > implement the semantics of 'K'.  Like 'i', 'k' will have to do an
> > explicit range test.
> 
> In my proposal these would then probably become PyInt_As1Byte, 
> PyInt_As2Bytes, PyInt_As4Bytes and PyInt_As8Bytes.

And what would their return types be?

--Guido van Rossum (home page: http://www.python.org/~guido/)