从'int'类型转换为'short unsigned int'可能会改变其值[-Wconversion]

时间:2018-01-14 16:16:51

标签: c

我不明白为什么编译器(GCC)在这一行抛出[-Wconversion]警告(代码工作正常)。

 uint16_t ICACHE_FLASH_ATTR crc(uint8_t data, uint16_t crc)
    {
        int i = 8;

        crc = crc ^ (uint16_t)data << 8; // <-- here

        do
        {
            if (crc & 0x8000)
                crc = crc << 1 ^ 0x1021; // <-- here
            else
                crc = crc << 1; // <-- and here
        } while (--i);

        return crc;
    }

所有操作数都是uint16_t所以为什么要抱怨?

如果常量被评估为int,我该怎样摆脱警告(不禁用它们)。

我也试过没运气

crc = crc ^ (uint16_t)data << 8UL;

谢谢,

1 个答案:

答案 0 :(得分:1)

假设机器有sizeof(int) == 4CHAR_BITS == 8(所以sizeof(int) > sizeof(uint16_t),C标准规定:

crc = crc ^ (uint16_t)data << 8;

经历了“通常的算术转换”,并且或多或少地被视为已经写过(8已经是int,因此它不会被转换):

crc = (uint16_t)( ((int)crc) ^ (((int)((uint16_t)data)) << 8) );

int变量uint16_t的赋值中分配xor运算符的crc结果会触发(准确地)警告。

类似的评论适用于标记的其他两行。

如果您正在使用sizeof(int) == sizeof(uint16_t)的计算机,则首先不会收到警告。

6.3.1.8 Usual arithmetic conversions

  

¶1许多期望算术类型操作数的运算符会导致转换并产生结果   以类似的方式输入类型。目的是确定操作数的通用实数类型   和结果。对于指定的操作数,将转换每个操作数,而不更改类型   域,对应的实类型是常见的实类型。除非   另外明确说明,常见的真实类型也是相应的实际类型   结果,其类型域是操作数的类型域,如果它们是相同的,   否则复杂。此模式称为通常的算术转换

     
      
  • ...浮点省略......

  •   
  • 否则,将对两个操作数执行整数提升。那么   以下规则适用于提升的操作数:

         
        
    • 如果两个操作数具有相同的类型,则无需进一步转换。

    •   
    • 否则,如果两个操作数都有有符号整数类型或两者都有无符号   整数类型,具有较小整数转换等级类型的操作数是   转换为具有更高等级的操作数的类型。

    •   
    • 否则,如果具有无符号整数类型的操作数的等级大于或等于   等于另一个操作数的类型的等级,然后是操作数   有符号整数类型转换为带有unsigned的操作数的类型   整数类型。

    •   
    • 否则,如果带有符号整数类型的操作数的类型可以表示   那么,带有无符号整数类型的操作数类型的所有值   具有无符号整数类型的操作数将转换为该类型   带有符号整数类型的操作数。

    •   
    • 否则,两个操作数都将转换为无符号整数类型   对应于带有符号整数类型的操作数的类型。
    •   
  •   

6.3.1.1 Boolean, characters, and integers说:

  

¶2...如果int可以表示原始类型的所有值(受宽度限制,对于a   位字段),该值转换为int;否则,它将转换为unsigned int。这些被称为整数提升 58)所有其他类型均未被   整数促销。

     

58)整数促销仅适用于:通常算术转换的一部分,以确定   参数表达式,一元+-~运算符的操作数,以及两个操作数的操作数   移位运算符,由各自的子条款指定。

§6.3.1.1¶1在难以置信的细节中定义'rank',但基本上较大的类型比较小的类型具有更高的等级(因此long具有比signed char更高的等级。)

然后,您可以找到各种运营商的规格:

6.5.7 Bitwise shift operators

  

每个操作数都应具有整数类型。

     

对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。

6.5.11 Bitwise exclusive OR operator

  

每个操作数都应具有整数类型。

     

通常的算术转换是在操作数上执行的。

6.5.16 Assignment operators

  

赋值运算符将值存储在左操作数指定的对象中。赋值表达式具有赋值后的左操作数的值, 111)但不是左值。赋值表达式的类型是左值操作数在左值转换后将具有的类型。

     

111)允许实现读取对象以确定值但不是必需的,甚至是   当对象具有volatile限定类型时。

6.5.16.1 Simple assignment

  

在简单赋值(=)中,右操作数的值将转换为   赋值表达式并替换存储在左侧指定的对象中的值   操作数。