Search code examples
c++qtchecksum

Increasing hex value with given data


I need to compare given text data with checkSumCalculator method and I try to send the data with command method. I find and changed the code according to my own needs. But I dont understand some parts. How can 0x00 hex char will be increase with given data? and how/what is the point of comparing check_data with 0xFF? How to extract (check_data & 0xFF) from 0x100 hex? I am very confused.

void Widget::command()
{
    std::string txt = "<DONE:8022ff";
    unsigned char check_sum = checkSumCalculator(&txt[0], txt.size());

    QString reply= QString::fromStdString(txt) + QString("%1>").arg(check_sum, 2, 16, 
QChar('0')); 
    emit finished(replyMessage, true);
}

static unsigned char checkSumCalculator(void *data, int length)
{
    unsigned char check_data = 0x00;
    for (int i = 0; i < lenght; i++)
        check_data+= ((unsigned char*)data)[i];

    check_data = (0x100 - (check_data & 0xFF)) & 0xFF;
    return check_data;
  }

Solution

  • checkSumCalculator starts by adding together all the values of the buffer in data. Because the type of data is unsigned char, this sum is done modulo 0x100 (256), 1 more than the maximum value an unsigned char can handle (0xFF = 255); the value is said to "wrap around" ((unsigned char) (0xFF + 1) = 256) is again 0).

    These two lines:

        check_data = (0x100 - (check_data & 0xFF)) & 0xFF;
        return check_data;
    

    are really more complicated than it's needed. All that would be needed would be:

        return -check_data;
    

    That is, at the end it negates the value. Because the arithmetic is modulo 256, this is essentially the same as flipping the bits and adding 1 (-check_data = ~check_data + 1). This is instead implemented in a more convoluted way:

    • check_data & 0xFF doesn't do much, because it's a bitwise AND with all the possible bits that can be set on an unsigned char. The value is promoted to an unsigned int (due to C's default integer promotions) where all the bits higher than the lower 8 are necessarily 0. So this is the same as (unsigned int)check_data. Ultimately, this promotion has no bearing on the result.
    • Subtracting from 0x100 is the same as -check_data, as far as the lower 8 bits are concerned (which what we end up caring about).
    • The final & 0xFF is also redundant because even though the expression was promoted to unsigned int, it will converted as an unsigned char by returning.