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

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


> > 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).
> 
> I would say strict on positive values, lenient on negative ones. 
> Not too lenient, of course: -0x100000000L should not be a passed 
> as 0 but give an exception.

I;m not sure I like this.  On the one hand this is what the struct
modules does currently for 'L'.  On the other hand it seems not to
provide any more safety than simply taking the low N bits (using 2's
complement for negative values) and throwing the rest away.

> This would correspond to everyday use in languages such as C.

Actually, C is fairly careful: AFAIK on a 32-bit machine the type of
0xffffffff is unsigned long, so it's not strictly -1, and you'll have
to use a cast somewhere to be able to compare it to an int.

> > 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).
> 
> ok. How about uint32_t? And, while we're at it, add Q for uint64_t?
> 
> >> In my proposal these would then probably become PyInt_As1Byte,
> >> PyInt_As2Bytes, PyInt_As4Bytes and PyInt_As8Bytes.
> >
> > And what would their return types be?
> 
> uint8_t, uint16_t, uint32_t and uint64_t.

Hm.  This is a big deviation from tradition.  Those types aren't
currently used or defined.

How about the following counterproposal.  This also changes some of
the other format codes to be a little more regular.

Code    C type          	Range check

b	unsigned char		0..UCHAR_MAX
B	unsigned char		none **
h	unsigned short		0..USHRT_MAX
H	unsigned short		none **
i	int			INT_MIN..INT_MAX
I *	unsigned int		0..UINT_MAX
l	long			LONG_MIN..LONG_MAX
k *	unsigned long		none
L	long long		LLONG_MIN..LLONG_MAX
K *	unsigned long long	none

Notes:

* New format codes.

** Changed from previous "range-and-a-half" to "none"; the
   range-and-a-half checking wasn't particularly useful.

If you need a uint32 mask, you can use the 'k' format and cast the
unsigned long you got to uint32; this should do the right thing.

If you really prefer your proposal with specific sized types, perhaps
you can show some coding example that would be easier using specific
sizes rather than char/short/int/long/long long?

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