LINUX.ORG.RU

История изменений

Исправление uin, (текущая версия) :

Не понял причем здесь переполнение.

Переполнение это когда ты умножаешь два положительных числа, а в результате получится -1 или 0 потому что регистра не хватит, чисто математически это недопустимо и ни в одном высокоуровневом языке не допустят такого и сишный компилятор тебя настоятельно предупредит что надо бы регистровое число расширить что бы не обосраться.

Здесь же сплошные битовые операции над 32 битами, никакие математические правила тут не действуют и соответственно никаких переполнений нет. Единственная битовая операция различающая число со знаком и без это математический сдвиг с зацеплением знака, и если вот здесь: i ^ crc >> 8 так и задумано что он может случится, то надо это писать как то явно что ли:

int qspCRC(void *ptr, int len)
{
    unsigned char *data = (unsigned char *)ptr;
    union {
        unsigned int u;
          signed int i;
    } tmp, crc = { .u = 0};

    for (int i = 0; i < len; i++) {
        tmp.i = qspCRCTable[(crc.u & 0xFF) ^ data[i]],
        crc.i = tmp.i ^ crc.i >> 8, // арифметический сдвиг из-за знаковых
        crc.u ^= 0xD202EF8Du;
    }
    return crc.i;
}

К тому же буквально только что узнал что арифметический сдвиг sar eax, 8 оказывается выполняется первым (только потом xor), а не как обычные битовые операции последовательно, поэтому с такой мешаниной надо быть аккуратней.

Исходная версия uin, :

Не понял причем здесь переполнение.

Переполнение это когда ты умножаешь два положительных числа, а в результате получится -1 или 0 потому что регистра не хватит, чисто математически это недопустимо и ни в одном высокоуровневом языке не допустят такого и сишный компилятор тебя настоятельно предупредит что надо бы регистровое число расширить что бы не обосраться.

Здесь же сплошные битовые операции над 32 битами, никакие математические правила тут не действуют и соответственно никаких переполнений нет. Единственная битовая операция различающая число со знаком и без это математический сдвиг с зацеплением знака, и если вот здесь: i ^ crc >> 8 так и задумано что он может случится, то надо это писать как то явно что ли:

int qspCRC(void *ptr, int len)
{
    unsigned char *data = (unsigned char *)ptr;
    union {
        unsigned int u;
          signed int i;
    } tmp, crc = { .u = 0};

    for (int i = 0; i < len; i++) {
        tmp.i = qspCRCTable[(crc.u & 0xFF) ^ data[i]],
        crc.i = tmp.i ^ crc.i >> 8, // арифметический сдвиг из-за знаковых
        crc.u ^= 0xD202EF8Du;
    }
    return crc.i;
}


К тому же буквально только что узнал что арифметический сдвиг sar %eax, 8 оказывается выполняется первым (только потом xor), а не как обычные битовые операции последовательно, поэтому с такой мешаниной надо быть аккуратней.