简体   繁体   中英

Read UInt types in binary

I am implementing a MidiReader And it need me to read weather MSB First or LSB First UInts(8, 16, 32 or 64). I know little about binary and types so I'm currently copying other's code from C#.

class ByteArrayReader
{
public:
    unsigned char* ByteArray;
    unsigned int Size;
    unsigned int Index = 0;

    ByteArrayReader(unsigned char* byteArray)
    {
        if (byteArray == NULL)
        {
            throw byteArray;
        }
        ByteArray = byteArray;
        Size = (unsigned int)sizeof(byteArray);
        Index = 0;
    }

    char inline Read()
    {
        return ByteArray[Index++];
    }

    void inline Forward(unsigned int length = 1)
    {
        Index += length;
    }

    void inline Backward(unsigned int length = 1)
    {
        if (length > Index)
        {
            throw length;
        }

        Index -= length;
    }

    bool operator==(ByteArrayReader) = delete;
};

These are what I copied:


    uint16_t inline ReadUInt16()
    {
        return (uint16_t)((Read() << 8) | Read());
    }

    uint32_t inline ReadUInt32()
    {
        return (uint32_t)((((((Read() << 8) | Read()) << 8) | Read()) << 8) | Read());
    }


But it's said that one of it reads MSB First UInt. So I want to ask how to read UInt types from binaries elegantly, also learning how uint is represented in bytes.

The part

(uint32_t)((((((Read() << 8) | Read()) << 8) | Read()) << 8) | Read());

is undefined behavior because each call to Read method increments a counter called Index and there is no strict order of computation of them by compiler.

It would be better if they were computed in order like this:

auto chunk1 = Read(); // Index=x
auto chunk2 = Read(); // Index=x+1
auto chunk3 = Read(); // Index=x+2
...
auto result = chunk1 << 8 | chunk2<<8 ...

to be sure incrementations are happening in order.

Order of bytes is different between little-endian and big-endian systems. Here it is asked: Detecting endianness programmatically in a C++ program

Try this:

uint32_t inline ReadUInt32MSBfirst()
{
    auto b1 = Read();
    auto b2 = Read();
    auto b3 = Read();
    auto b4 = Read();
    return (uint32_t)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
}

uint32_t inline ReadUInt32LSBfirst()
{
    auto b1 = Read();
    auto b2 = Read();
    auto b3 = Read();
    auto b4 = Read();
    return (uint32_t)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM