Search code examples
pythonctypesbit-fieldssign-extension

Bit field specialization in python


Here is a code in C++:

void sign_extending(int x)
{
  int r; // resulting sign extended number goes here
  struct {signed int x:5 ;} s;
  r = s.x = x;
  cout << r; 
}

void Run()
{
  int x=29; // this 29 is -3 ( 11101 ) in 5 bits 
  // convert this from using 5 bits to a full int
  sign_extending(x);
}

The output of this code is -3. When i try to reproduce this code in python the bit field of 11101 is generated but when the answer is converted to an int the answer of 29 is given .

the following is code of python:

from bitarray import *

def sign_extending(x) :
  s = bitarray(5)
  r = s = bin(x)  #resulting sign extended number goes in r
  print (int(r, 2))

x = 29 #this 29 is -3 ( 11101 ) in 5 bits. Convert this from using 5 bits to a full int
sign_extending(x)

I also used ctypes structures as an alternative code but no use :

from ctypes import *
def sign_extending(x, b):
  class s(Structure):
      _fields_ = [("x", c_int, 5)]
  r = s.x = x
  return r  #resulting sign extended number goes in r

x = 29; #this 29 is -3 ( 11101 ) in 5 bits. 
r = sign_extending(x, 5) #Convert this from using 5 bits to a full int
print r

My question is that how would i produce this result using bit arrays or any other method that gives the correct answer.


Solution

  • In your code s is a class and the class x member actually represents the field type, so assigning s.x = 29 essentially destroys that object and assigns a normal Python int to it. Example:

    >>> from ctypes import *
    >>> class S(Structure):
    ...     _fields_ = [('x',c_int,5)]
    ... 
    >>> S.x
    <Field type=c_long, ofs=0:0, bits=5>
    >>> S.x = 29
    >>> S.x
    29
    

    Also, even if you create an instance first, r = s.x = 29 does not do s.x = 29 then r = s.x as in C/C++ but essentially r=29 and s.x=29. Example:

    >>> from ctypes import *
    >>> class S(Structure):
    ...     _fields_ = [('x',c_int,5)]
    ...     
    >>> s=S()
    >>> r=s.x=29
    >>> s.x
    -3
    >>> r
    29
    

    So to fix, instantiate the class, assign s.x = 29 and return it:

    from ctypes import *
    def sign_extending(x, b):
        class S(Structure):
            _fields_ = [("x", c_int, b)]
      s=S()
      s.x = x
      return s.x
    
    x = 29; #this 29 is -3 ( 11101 ) in 5 bits. 
    r = sign_extending(x, 5) #Convert this from using 5 bits to a full int
    print r
    

    Output:

    -3