在 if 语句中定义的局部变量意外出现

ori*_*and 1 c++ cross-platform undefined-behavior

最初我想将一堆语句打包成一行,这样我的东西就可以用作 if 中的简单宏。我需要做三件事:

  • 创建局部变量
  • 用函数更新它
  • 检查更新的变量是否匹配其他内容

这是我的快速草稿代码:

#include <iostream>
#include <stdint.h>
#define MAGIC_VALUE 42

bool MyMockedFunction(uint64_t* outElement)
{
    *outElement = MAGIC_VALUE;

    return true;
}

static const uint64_t global_should_match_this = MAGIC_VALUE;

int main()
{
    // Originally I wanted to declare the variable in one single line (as a defined macro, which should be used in an IF statement)
    // That's why I have so many things packed into the same line
    // It may or may not (latter is more probable) a good idea, but that's not the question here

    if (uint64_t generatedElement = 123456 && MyMockedFunction(&generatedElement) && global_should_match_this == generatedElement)
    {
        // I would expect generatedElement == MAGIC_VALUE
        printf("Inside value: %llu\n", generatedElement);
    }
    else
    {
        printf("Unmatched\n");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我知道以编程方式它可能不是万无一失的,如果我将它放在宏中很容易被误用(宏也是邪恶的),但在我的情况下,这将是一个非常受控制的环境,只是为了使我的代码更易于阅读。

那么,问题就在这里 - 为什么生成的元素在运行后等于 1?这是一种未定义的行为吗?

我已经在编译器反汇编器中检查它是 1,因为最后比较的值(表达式是否为真?是 -> 1 -> 这就是移入变量的内容。但对我来说它看起来不合理。为什么编译器会这样做所以?:O 在 MSVC 和 GCC 上都检查过,两者都产生相同的输出。

Som*_*ude 5

你的情况真的是:

uint64_t generatedElement = (123456 && MyMockedFunction(&generatedElement) && global_should_match_this == generatedElement)
Run Code Online (Sandbox Code Playgroud)

这意味着您generatedElement使用布尔结果进行初始化。而且还导致不确定的行为,所使用的未初始化的(和不确定的)价值generatedElement

如果您的编译器支持if带有初始化程序的语句(C++17 中的新功能),那么您可以这样做

if (uint64_t generatedElement = 123456; MyMockedFunction(&generatedElement) && global_should_match_this == generatedElement)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

否则,您必须拆分为单独的变量定义和条件:

uint64_t generatedElement = 123456;
if (MyMockedFunction(&generatedElement) && global_should_match_this == generatedElement)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)