c - 为什么没有类型转换警告?

标签 c gcc embedded clang

我有以下 C 代码片段,在 Clang 中启用了 -Wconversion:

uint8_t num_ch = get_num_channels();
uint64_t test_mask = 1 << num_ch;
我希望这会引发某种警告,因为 1 是一个隐式的“signed int”,然后被分配给 uint64_t,但编译器没有提示:(
我错过了什么?

最佳答案

Why no type conversion warning?


简短回答:因为您使用的 clang/LLVM 版本中存在缺陷(有些人甚至可能称其为错误)。
讨论/说明/推理
该问题源于对位移表达式的评估,s << u ,其中 s是有符号整数类型和 u是无符号类型。现在,根据this C11 Draft Standard (粗体我的):

6.5.7 Bitwise shift operators
...
3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.


这意味着表达式的结果是一个有符号整数。从今以后,我应该指出,我正在使用(并假设)一个使用 32 位“基本”的平台 int类型。另请注意,没有 u 的整数常量suffix 是有符号类型。
注意:虽然我无法访问 OP 的嵌入式系统,也无法访问本地 GCC 编译器,但我仍然可以使用 重现该问题。 clang-cl 最新版本的 Visual Studio 2019 中提供的编译器(16.7.2 - 当我发现它是什么时,我会添加 clang 版本)。
以下代码 生成预期的警告(实际上是两个警告,如图所示):
#include <stdio.h>
#include <stdint.h>

int main()
{
    uint64_t test_mask = 1 << (uint8_t)(31); // Warnings here, as expected.
    printf("%016llX\n", test_mask);
    return 0;
}
警告:

warning : signed shift result (0x80000000) sets the sign bit of the shift expression's type ('int') and becomes negative [-Wshift-sign-overflow]
warning : implicit conversion changes signedness: 'int' to 'uint64_t' (aka 'unsigned long long') [-Wsign-conversion]


此外,printf 的输出电话是 FFFFFFFF80000000 ,这说明了为什么警告很重要:位移(在 32 位 int 上)产生了一个负值,然后在提升为 64 位时进行符号扩展 - 因此“破坏”了预期/预期结果(如果文字 0000000080000000 只是简单地更改为 1 ,则将是 1u ,从而避免符号扩展)。
然而!如果对代码进行了非常小的(有些人甚至可能说微不足道的)更改,将位移的文字(常量)右侧操作数更改为完全等效的变量,如下面的代码所示,则警告来自 clang-cl 消失(但输出仍然“损坏”-因此执行的操作相同)。
int main()
{
    uint8_t num_ch = 31;
    uint64_t test_mask = 1 << num_ch; // No warning here!
    printf("%016llX\n", test_mask);
    return 0;
}
可能不是最有帮助的答案 - 但除了向 LLVM 的人报告问题之外,还能做些什么呢?我肯定会提交这样的报告,因为 OP 发布的代码可能会导致一些严重的问题,这些问题应该由启用了完整警告的编译器检测和指示(MSVC 甚至会针对第二个代码片段发出警告)。

关于c - 为什么没有类型转换警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63624685/

相关文章:

performance - 在 ARM 开发板上测量应用程序性能

c - 为什么我的 HAL_UART IT 捕获回调例程不会触发?

c++ - 如何检查是否发生了内联

c++ - 求图形显示/C++中(头文件)文件依赖关系的工具

c++ - 关于 -fPIC 的链接错误,即使所有源代码都是使用 -fPIC 编译的

c++ - 在大型 C/C++ 项目的编译时使用 GNU m4

c - "multiple definition of ` memcmp“链接Rust staticlib与嵌入式C程序时出错

c - 尝试自动化 git,只提交名为 "T"

c - 使用 execvp 时输入重定向问题?

c - 我收到错误 : expected '=' , ',' 、 ';' 、 'asm' 或 '' __attribute_ _' before ' void'