分配给更广泛的基本类型的表达式
Expression assigned to a wider essential type
我从我们的分析工具中收到以下警告 Composite expression assigned to a wider essential type
这是代码:
uint32_t result;
uint8_t resolution;
result = 1U << resolution;
我尝试了以下方法:
#define SHIFT_BY_ONE (uint8_t)1
result = SHIFT_BY_ONE << resolution;
但那会引发此警告 Shift left of signed quantity (int)
所以我想我没有正确理解这个问题。我该如何解决这个错误?
在您的系统上 1U
可能是 16 位无符号的(这解释了在尝试分配给 32 位无符号时的 "wider type")。
在那种情况下,我会使用 long
后缀作为文字:
result = 1UL << resolution;
(一些评论建议 ((uint32_t)1U) << resolution
这毕竟是最便携的方式)
发生这种情况是因为 1U
与 uint32_t
类型不匹配。使用 确保类型兼容性:
result = UINT32_C(1) << resolution;
这听起来好像您是 运行 MISRA-C:2012 检查员。 基本类型和复合表达式是MISRA-C中的术语,而不是C标准中的术语。
为了从这个警告中理解任何东西,你必须研究基本类型 (MISRA-C:2012 8.10) 和复合表达式 (MISRA-C:2012 8.10.3) 的含义。
至于警告的原因,是规则10.6:
The value of a composite expression shall not be assigned to an object with wider essential type.
如果我们忽略所有这些术语的含义,则规则归结为如果您有一个具有 2 个较小类型的操作数的运算,则结果不应分配给比那些更大类型的变量操作数。
这是为了防止这样的代码:
uint16_t a = 40000;
uint16_t b = 40000;
uint32_t result = a + b;
在 16 位系统上,操作数 a
和 b
不会被提升,因此实际操作将在 16 位类型上执行 - 并且会有一个无符号换行 -周围(或在有符号变量的情况下溢出)。
不理解隐式类型提升在 C 中是如何工作的困惑的程序员可能认为上述操作在 uint32_t
上执行只是因为结果存储在这样的类型中。但这是不正确的,赋值运算符的左侧与子表达式 a + b
无关。子表达式中使用哪种类型完全由运算符优先级决定,=
的优先级低于 +
.
显然 MISRA-C 认为这种误解很普遍,这就是这条规则的基本原理。
至于怎么解决,很简单:
result = (uint32_t)1U << resolution;
1U
可能比 uint32_t
更窄(16 位),因此 "Composite expression assigned to a wider essential type"。将 16 位 unsigned
移位 20 不会得到 0x100000,
uint32_t result;
uint8_t resolution;
result = 1U << resolution; // Potential 16-bit assignment to a 32-bit type.
resolution
的狭窄在这里不是问题。
How do I fix this error?
我更愿意在可能的情况下避免转换并提供 2 个替代方案。两者都首先有效地创建目标类型的 1
而无需强制转换。编译器肯定会发出优化代码。
result = 1u;
result <<= resolution;
// or
result = (result*0u + 1u) << resolution;
我从我们的分析工具中收到以下警告 Composite expression assigned to a wider essential type
这是代码:
uint32_t result;
uint8_t resolution;
result = 1U << resolution;
我尝试了以下方法:
#define SHIFT_BY_ONE (uint8_t)1
result = SHIFT_BY_ONE << resolution;
但那会引发此警告 Shift left of signed quantity (int)
所以我想我没有正确理解这个问题。我该如何解决这个错误?
在您的系统上 1U
可能是 16 位无符号的(这解释了在尝试分配给 32 位无符号时的 "wider type")。
在那种情况下,我会使用 long
后缀作为文字:
result = 1UL << resolution;
(一些评论建议 ((uint32_t)1U) << resolution
这毕竟是最便携的方式)
发生这种情况是因为 1U
与 uint32_t
类型不匹配。使用
result = UINT32_C(1) << resolution;
这听起来好像您是 运行 MISRA-C:2012 检查员。 基本类型和复合表达式是MISRA-C中的术语,而不是C标准中的术语。
为了从这个警告中理解任何东西,你必须研究基本类型 (MISRA-C:2012 8.10) 和复合表达式 (MISRA-C:2012 8.10.3) 的含义。
至于警告的原因,是规则10.6:
The value of a composite expression shall not be assigned to an object with wider essential type.
如果我们忽略所有这些术语的含义,则规则归结为如果您有一个具有 2 个较小类型的操作数的运算,则结果不应分配给比那些更大类型的变量操作数。
这是为了防止这样的代码:
uint16_t a = 40000;
uint16_t b = 40000;
uint32_t result = a + b;
在 16 位系统上,操作数 a
和 b
不会被提升,因此实际操作将在 16 位类型上执行 - 并且会有一个无符号换行 -周围(或在有符号变量的情况下溢出)。
不理解隐式类型提升在 C 中是如何工作的困惑的程序员可能认为上述操作在 uint32_t
上执行只是因为结果存储在这样的类型中。但这是不正确的,赋值运算符的左侧与子表达式 a + b
无关。子表达式中使用哪种类型完全由运算符优先级决定,=
的优先级低于 +
.
显然 MISRA-C 认为这种误解很普遍,这就是这条规则的基本原理。
至于怎么解决,很简单:
result = (uint32_t)1U << resolution;
1U
可能比 uint32_t
更窄(16 位),因此 "Composite expression assigned to a wider essential type"。将 16 位 unsigned
移位 20 不会得到 0x100000,
uint32_t result;
uint8_t resolution;
result = 1U << resolution; // Potential 16-bit assignment to a 32-bit type.
resolution
的狭窄在这里不是问题。
How do I fix this error?
我更愿意在可能的情况下避免转换并提供 2 个替代方案。两者都首先有效地创建目标类型的 1
而无需强制转换。编译器肯定会发出优化代码。
result = 1u;
result <<= resolution;
// or
result = (result*0u + 1u) << resolution;