繁体   English   中英

将 32 位值存储在 64 位变量中时 C++ 发出警告

C++ warn when storing 32 bit value in a 64 bit variable

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我最近在我正在处理的项目中发现了一个很难找到的错误。 问题是我们做了一个有uint32_t结果的计算,并将它存储在一个uint64_t变量中。 我们预计结果是uint64_t ,因为我们知道结果对于 32 位无符号整数来说可能太大了。

我的问题是:有没有办法让编译器(或像 clang-tidy 这样的静态分析工具)在发生这种情况时警告我?

一个例子:

#include <iostream>

constexpr uint64_t MUL64 { 0x00000000ffffffff };
constexpr uint32_t MUL32 { 0xffffffff };

int main() {
    const uint32_t value { 0xabababab };

    const uint64_t value1 { MUL64 * value }; // the result is a uint64_t because
                                             // MUL64 is a uint64_t
    const uint64_t value2 { MUL32 * value }; // i'd like to have a warning here

    if (value1 == value2) {
        std::cout << "Looks good!\n";
        return EXIT_SUCCESS;
    }
    std::cout << "Whoopsie\n";
    return EXIT_FAILURE;
}

编辑:

溢出是预期的,即我们知道我们需要一个uint64_t来存储计算值。 我们也知道如何解决这个问题,后来我们将其更改为:

const uint64_t value2 { static_cast<uint64_t>(MUL32) * value };

这样在计算过程中就不会切断高 32 位。 但是这样的事情还是时有发生,我只是想知道有没有办法检测到这种错误。

提前致谢!

问候,
塞巴斯蒂安

1 个回复

无符号整数类型的乘法行为被很好地定义为将模2转换为整数类型宽度的幂。 因此,这里没有任何编译器可以警告的内容。 该行为是预期的并且可能是故意的。 警告它会产生太多的误报。

此外,通常编译器无法在常量表达式评估之外的编译时测试溢出。 在这种特定情况下,这些值很明显,它可以做到这一点。

关于算术后任何扩大转换的警告很可能也很嘈杂。

由于上述原因,我不知道有任何编译器标志会添加警告。


Clang-tidy 确实有一个名为bugprone-implicit-widening-of-multiplication-result的检查,专门用于以较窄类型执行乘法然后隐式加宽的这种情况。 似乎自 LLVM 13 以来就存在检查。但我认为没有等价的添加。

此检查按预期在这里工作:

<source>:11:29: warning: performing an implicit widening conversion to type 'const uint64_t' (aka 'const unsigned long') of a multiplication performed in type 'unsigned int' [bugprone-implicit-widening-of-multiplication-result]
    const uint64_t value2 { MUL32 * value }; // i'd like to have a warning here
                            ^
<source>:11:29: note: make conversion explicit to silence this warning
    const uint64_t value2 { MUL32 * value }; // i'd like to have a warning here
                            ^~~~~~~~~~~~~
                            static_cast<const uint64_t>( )
<source>:11:29: note: perform multiplication in a wider type
    const uint64_t value2 { MUL32 * value }; // i'd like to have a warning here
                            ^~~~~
                            static_cast<const uint64_t>()

Clang 的未定义行为清理程序还有一个检查,可以在运行时标记所有无符号整数溢出,这通常不包含在-fsanitize=undefined中。 它可以包含在-fsanitize=unsigned-integer-overflow中。 这很可能需要为预期的环绕行为添加抑制。 有关详细信息,请参阅https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

然而,这里似乎没有应用此检查,因为算术是由编译器在编译时执行的。 如果您删除value2上的const ,UBSan 会捕捉到它:

/app/example.cpp:11:29: runtime error: unsigned integer overflow: 4294967295 * 2880154539 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:11:29 in 
Whoopsie

GCC 似乎没有等效的选择。


如果您希望在无符号算术中对溢出发出一致的警告,您需要围绕执行溢出检查的整数类型定义自己的包装类,例如,如果失败则抛出异常,或者您可以实现溢出安全加法/乘法的函数然后,您将不得不使用而不是+*运算符。

4 计数 session 数组中的值时发出警告

自从升级到 PHP 7.2 后,我现在在尝试获取 PHP session 中的值数量时收到此警告 我尝试用来获取值数量的代码是 和 我认为 php session 是一个数组,但我的理解似乎不正确,但我不确定如何将 session 转换为数组。 话虽如此,将我的代码保留原样会导致我进一步出现问题吗? ...

6 C ++全局变量未显式初始化时发出警告?

假设我有一个全局(或名称空间范围)变量,如: 当然,这是零初始化,但Clang(或使用Clang的静态分析工具)是否有办法警告Pointer未被明确初始化? 我搜索过,找不到任何东西。 ...

7 C ++:从32位到64位的迁移

我正在研究一个迁移32位C++代码以在Mac OS X上同时在32位和64位模式下工作的项目。 我对某些事情感到困惑。 例如,请考虑以下几行代码- 现在,我知道sizeof(long)将在32位返回4 ,在64位返回8 。 因此,我对于通常应该替换上面两行的内容感到困惑,以至于这些 ...

8 64位变量存储为32位

在ARM交叉编译器中使用unsigned long long类型的变量进行编译时遇到了一些问题 该变量表示分区大小(~256GBytes)。 我希望它存储为64位,但在使用%lld打印它,或者甚至尝试将其打印为Mega字节(value/(1024*1024*1024)) ,我总是看到它的 ...

9 在C ++中设置64位变量

我想知道如何在C ++中为我的测试台设置64位变量。 当我使用variable_name.io_int_write(0,value0)和variable_name.io_int_write(1,value1) (用于低位和高位)时,我可以看到变量已设置但以相反的方式进行。 例如:当我希望 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM