我不明白为什么编译器(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;
谢谢,
答案 0 :(得分:1)
假设机器有sizeof(int) == 4
和CHAR_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:
每个操作数都应具有整数类型。
通常的算术转换是在操作数上执行的。
赋值运算符将值存储在左操作数指定的对象中。赋值表达式具有赋值后的左操作数的值, 111)但不是左值。赋值表达式的类型是左值操作数在左值转换后将具有的类型。
111)允许实现读取对象以确定值但不是必需的,甚至是 当对象具有volatile限定类型时。
在简单赋值(
=
)中,右操作数的值将转换为 赋值表达式并替换存储在左侧指定的对象中的值 操作数。