C Zephyr SDK CRC16实施

问题描述 投票:0回答:1

我在zephyr的实现中找到了这个计算crc16校验和的方法。

u16_t crc16(const u8_t *src, size_t len, u16_t polynomial,
        u16_t initial_value, bool pad)
{
    u16_t crc = initial_value;
    size_t padding = pad ? sizeof(crc) : 0;
    size_t i, b;

    /* src length + padding (if required) */
    for (i = 0; i < len + padding; i++) {

        for (b = 0; b < 8; b++) {
            u16_t divide = crc & 0x8000UL;

            crc = (crc << 1U);

            /* choose input bytes or implicit trailing zeros */
            if (i < len) {
                crc |= !!(src[i] & (0x80U >> b));
            }

            if (divide != 0U) {
                crc = crc ^ polynomial;
            }
        }
    }

    return crc;
}

我被这一行绊倒了

                crc |= !!(src[i] & (0x80U >> b));

我不明白为什么这一行要用布尔运算符 (!). 根据我的理解,它是这样做的:它基本上做了一个隐式的 "铸造",它认为右边的操作数是一个布尔运算符,并否定了它两次,除了使输出为0或1之外,它没有做任何事情,这取决于表达式 (src[i] & (0x80U >> b)) 一开始就是大于0的,这样做对吗?为什么他们要这样使用运算符?

c crc
1个回答
0
投票

它是插入位 7-bsrc[i] 到低位的 crc. 如果该位是一个 1的结果中的某处。&జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ !! 变成 1 的低位,然后再将其转化为 crc.

这真是让人看了很痛苦。更好、更干净的方法是 crc |= (src[i] >> b) & 1;,其中 b 向下数而不是向上数。如:. int b = 8; do { b--; ... } while (b);. 更好的办法是只用独占--或者循环后的字节,这样做是一样的。

/* src length + padding (if required) */
for (i = 0; i < len + padding; i++) {
    for (b = 0; b < 8; b++)
        crc = crc & 0x8000 ? (crc << 1) ^ polynomial : crc << 1;
    if (i < len)
        crc ^= src[i];
}

一个优化的编译器会在循环后展开 b 循环。

© www.soinside.com 2019 - 2024. All rights reserved.