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)

    http://groups.google.co.uk/group/comp.lang.python/msg/2c411ca9251774dc

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

    http://groups.google.co.uk/group/comp.lang.python/msg/359927a23eb15b3e


the encoding of -1073448320 would be

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

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

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

 >>> bcd('0101',2)
 5
 >>> bcd('1101',2)
 -3

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

 >>> bcd('11111111111111111101',2)
 -3
 >>> bcd('00000000000000000101',2)
 5

irrespective of the base:

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

>
>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).
</rant>

Regards,
Bengt Richter



More information about the Python-list mailing list