Converting 24 bit integer (2s complement) to 32 bit integer in C++

10,212

I am not understanding how I can store the CHAR "data" into an INT.

Since char is a numeric type, there is no problem combining them into a single int.

Since its receiving 24 integers of information stored into a BYTE

It's 24 bits, not bytes, so there are only three integer values that need to be combined.

An easier way of producing the same result without using conditionals is as follows:

int interpret24bitAsInt32(byte[] byteArray) {     
    return (  
        (byteArray[0] << 24)
    |   (byteArray[1] << 16)
    |   (byteArray[2] << 8)
    ) >> 8;  
}

The idea is to store the three bytes supplied as an input into the upper three bytes of the four-byte int, and then shift it down by one byte. This way the program would sign-extend your number automatically, avoiding conditional execution.

Note on portability: This code is not portable, because it assumes 32-bit integer size. To make it portable use <cstdint> types:

int32_t interpret24bitAsInt32(const std::array<uint8_t,3> byteArray) {
    return (  
        (const_cast<int32_t>(byteArray[0]) << 24)
    |   (const_cast<int32_t>(byteArray[1]) << 16)
    |   (const_cast<int32_t>(byteArray[2]) << 8)
    ) >> 8; 
}

It also assumes that the most significant byte of the 24-bit number is stored in the initial element of byteArray, then comes the middle element, and finally the least significant byte.

Note on sign extension: This code automatically takes care of sign extension by constructing the value in the upper three bytes and then shifting it to the right, as opposed to constructing the value in the lower three bytes right away. This additional shift operation ensures that C++ takes care of sign-extending the result for us.

Share:
10,212
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin about 2 years

    The dataFile.bin is a binary file with 6-byte records. The first 3 bytes of each record contain the latitude and the last 3 bytes contain the longitude. Each 24 bit value represents radians multiplied by 0X1FFFFF

    This is a task I've been working on. I havent done C++ in years so its taking me way longer than I thought it would -_-. After googling around I saw this algorthim which made sense to me.

    int interpret24bitAsInt32(byte[] byteArray) {     
     int newInt = (  
         ((0xFF & byteArray[0]) << 16) |  
         ((0xFF & byteArray[1]) << 8) |   
         (0xFF & byteArray[2])  
       );  
     if ((newInt & 0x00800000) > 0) {  
       newInt |= 0xFF000000;  
     } else {  
       newInt &= 0x00FFFFFF;  
     }  
    return newInt;  
    }  
    

    The problem is a syntax issue I am restricting to working by the way the other guy had programmed this. I am not understanding how I can store the CHAR "data" into an INT. Wouldn't it make more sense if "data" was an Array? Since its receiving 24 integers of information stored into a BYTE.

    double BinaryFile::from24bitToDouble(char *data) {
        int32_t iValue;
    
        // ****************************
        // Start code implementation
        // Task: Fill iValue with the 24bit integer located at data.
        // The first byte is the LSB.
        // ****************************
    //iValue += 
        // ****************************
        // End code implementation
        // ****************************
        return static_cast<double>(iValue) / FACTOR;
    }
    
    bool BinaryFile::readNext(DataRecord &record)
    {
        const size_t RECORD_SIZE = 6;
        char buffer[RECORD_SIZE];
        m_ifs.read(buffer,RECORD_SIZE);
        if (m_ifs) {
            record.latitude = toDegrees(from24bitToDouble(&buffer[0]));
            record.longitude = toDegrees(from24bitToDouble(&buffer[3]));
            return true;
        }
        return false;
    }
    
    double BinaryFile::toDegrees(double radians) const
    {
        static const double PI = 3.1415926535897932384626433832795;
        return radians * 180.0 / PI;
    }
    

    I appreciate any help or hints even if you dont understand a clue or hint will help me alot. I just need to talk to someone.

  • Sergey Kalinichenko
    Sergey Kalinichenko over 8 years
    @SergeyA Oops, I indeed copy-pasted more than was necessary. Thanks!
  • hetepeperfan
    hetepeperfan over 3 years
    If one would read a 24bit 2's complement little endian signed integer from a file, doesn't one need to bitshift the sign bit, when converting to a int32_t?
  • Sergey Kalinichenko
    Sergey Kalinichenko over 3 years
    @hetepeperfan This is an excellent observation, thank you. Sing-extension is already happening because of the shift right >> operation. See a note I added at the bottom.