2.3 -> 2.4: long int too large to convert to int

Bengt Richter bokr at oz.net
Fri Sep 16 10:53:56 CEST 2005

On Fri, 16 Sep 2005 01:25:30 -0000, Grant Edwards <grante at visi.com> wrote:

>On 2005-09-15, Terry Reedy <tjreedy at udel.edu> wrote:
>>>I give up, how do I make this not fail under 2.4?
>>> fcntl.ioctl(self.dev.fileno(),0xc0047a80,struct.pack("HBB",0x1c,0x00,0x00))
>>> I get an OverflowError: long int too large to convert to int
>>> ioctl() is expecting a 32-bit integer value, and 0xc0047a80 has
>>> the high-order bit set.  I'm assuming Python thinks it's a
>>> signed value.  How do I tell Python that 0xc0047a80 is an
>>> unsigned 32-bit value?
>> In 2.3 and before, you get this:
>>>>> 0xc0047a80
>> -1073448320
>I don't particular care how Python prints the value -- I just
>want that value passed to the function I'm calling.
I do care, dang it. IMIFO (in my increasingly frustrated opinion ;-)
one ought to be able to write literals for negative integers.
A simple variation on 0x... coul be 0h... where what follows 0h is
base-16-complement, which turns out to be 0hfc0047a80 for the negative
number you want, and would be 0h0c0047a80 if you wanted the positive number
with the same least significant bits.

>> In 2.4, positive hex literals are treated as positive numbers, and that is 
>> your problem: your literal is greater than the largest int and hence gets 
>> stored as long int.
>I knew that, I just couldn't come up with a good way to fix it.
IMO you shouldn't have to fight it.
>> I would try -1073448320 as the arg.
>That should work, but it's kind of lame (no offense).
Yes, it is lame ;-)

see more on the notation (of which hex is only the particular base-16 case)


(It doesn't show in the examples, but unfortunately the code has a bug that I fixed
in a later post,


the encoding of -1073448320 would be

 >>> from ut.basecompl import basecompl as bc, bcdecode as bcd
 >>> '0h'+bc(-1073448320, 16)

or you could use other bases with 0b<base>. prefix:

 >>> '0b2.'+bc(-1073448320, 2)
 >>> '0b8.'+bc(-1073448320, 8)
 >>> '0b16.'+bc(-1073448320, 16)
 >>> '0b10.'+bc(-1073448320, 10)
       -1073448320  note the correspondence to previous line for base 10 ;-)

 >>> bcd('0101',2)
 >>> bcd('1101',2)

repeating the "sign digit" doesn't change the decoded value:

 >>> bcd('11111111111111111101',2)
 >>> bcd('00000000000000000101',2)

irrespective of the base:

 >>> bcd('98926551680', 10)
 >>> bcd('99999999999999998926551680', 10)
 >>> bcd('fc0047a80', 16)
 >>> bcd('fffffffffffffffffffc0047a80', 16)

>ioctl values are always, always written in hex.  A block of
>ioctl values is generally assigned to a particular driver such
>that the high order N (is it 4 oe 5?) hex digits are unique to
>that driver.  Writing the value in decimal is going to
>completely confuse anybody looking at the code.
>I rather like the other suggestion of writing a function that
>accepts 0x<whatever> and returns the appropriate integer value.
Sure, but there's no reason we shouldn't be allowed to specify a constant
as a literal IMO.

>Another poster suggested a solution using struct.  Here's my
>solution (which assume python integers are represented in 2's
>compliment binary):
>def ioctlValue(i):
>    if i & 0x80000000:
>        i = -((i^0xffffffff)+1)
>    return i
Do you think it's PEP-able, or should I quit being obnoxious ;-)

I think str.mod format like %x except %<width>.<base>b would make it
easy to write '0h%08b.16' % a_signed_integer and get something both
readable and inputtable as a constant. (0h.<the rest> would be short
for 0b16.<the rest>) BTW, %b (or %B for uppercase) could default to base 16.
The ouput would only be as wide as necessary, with the leading digit
guaranteed 0 or f (which is 0 or <base-1> in the general case).

Bengt Richter

More information about the Python-list mailing list