这是 C++ 中未定义的行为吗?

发布于 2024-12-26 17:48:32 字数 175 浏览 4 评论 0原文

我想知道下面最后一个 if 中对 x 的访问是否是未定义的行为:

int f(int *x)
{
    *x = 1;
    return 1;
}

int x = 0;
if (f(&x) && x == 1) {
    // something
}

I was wondering whether the access to x in the last if below here is undefined behaviour or not:

int f(int *x)
{
    *x = 1;
    return 1;
}

int x = 0;
if (f(&x) && x == 1) {
    // something
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

孤者何惧 2025-01-02 17:48:32

不是未定义的行为,因为运算符&&是一个序列点

It's not undefined behavior as operator && is a sequence point

妄司 2025-01-02 17:48:32

它有明确的定义。

参考 - C++03 标准:

第 5 节:表达式,第 4 段:

除非另有说明[例如&&的特殊规则和 ||]、各个运算符的操作数和各个表达式的子表达式的求值顺序以及副作用发生的顺序是未指定

期间,

第 1.9.18 节

在计算以下表达式时

a &&乙
一个 ||乙
一个?乙:丙
, 乙

使用这些表达式中运算符的内置含义,在第一个表达式求值之后有一个序列点 (12)。

It is well defined.

Reference - C++03 Standard:

Section 5: Expressions, Para 4:

except where noted [e.g. special rules for && and ||], the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is Unspecified.

While in,

Section 1.9.18

In the evaluation of the following expressions

a && b
a || b
a ? b : c
a , b

using the built-in meaning of the operators in these expressions, there is a sequence point after the evaluation of the first expression (12).

用心笑 2025-01-02 17:48:32

它被定义了。 C/C++ 进行惰性求值,并定义首先计算并检查左表达式。如果这是真的,那么就是正确的。

It is defined. C/C++ do lazy evaluation and it is defined that first the left expression will be calculated and checked. If it is true then the right one will be.

若无相欠,怎会相见 2025-01-02 17:48:32

不可以,因为 && 定义了一种顺序,其中左轴必须在右轴之前计算。

||?:, 上也有定义的顺序。其他操作数上没有。

在可比较中:

int x = 0;
if (f(&x) & x == 1) {
    // something
}

那么它是未定义的。此处,左侧和右侧都将按任意顺序进行计算。这种逻辑的非捷径形式不太常见,因为捷径通常被认为至少对性能有益,而且通常对正确性至关重要。

No, because && defines an ordering in which the lhs must be computed before the rhs.

There is a defined order also on ||, ?: and ,. There is not on other operands.

In the comparable:

int x = 0;
if (f(&x) & x == 1) {
    // something
}

Then it's undefined. Here both the lhs and rhs will be computed and in either order. This non-shortcutting form of logical and is less common because the short-cutting is normally seen as at least beneficial to performance and often vital to correctness.

抚笙 2025-01-02 17:48:32

这不是未定义的行为。原因取决于两个事实,两者都足以给出定义的行为

  • 函数调用和终止是一个序列点
  • “&&”运算符是一个序列点

下面也是定义的行为

int f(int *x) {
    *x = 1;
    return 1;
}

int x = 0;
if (f(&x) & (x == 1)) {
    // something
}

但是,您不知道 x == 1 的计算结果是 true 还是 false,因为 & 的第一个或第二个操作数可以首先被评估。不过,这对于定义此代码的行为并不重要。

It is not undefined behavior. The reason depends on two facts, both are sufficient for giving defined behavior

  • A function call and termination is a sequence point
  • The '&&' operator is a sequence point

The following is defined behavior too

int f(int *x) {
    *x = 1;
    return 1;
}

int x = 0;
if (f(&x) & (x == 1)) {
    // something
}

However, you don't know whether x == 1 evaluates to true or false, because either the first or the second operand of & can be evaluated first. That's not important for the behavior of this code to be defined, though.

油焖大侠 2025-01-02 17:48:32

它不是未定义的,但也不应该编译,因为您试图将指向 x (&x) 的指针分配给引用。

&& 将从左到右进行计算(如果左侧计算结果为 false,则计算将停止)。

编辑:通过更改,它应该可以编译,但仍然会被定义(因为如果您使用指针或引用并不重要)。

It's not undefined, but it shouldn't compile either, as you're trying to assign a pointer to x (&x) to a reference.

&& will be evaluated from left to right (evaluation will stop, if the left side evaluates false).

Edit: With the change it should compile, but will still be defined (as it doesn't really matter if you use a pointer or reference).

好听的两个字的网名 2025-01-02 17:48:32

它将调用者块中局部变量x的地址作为参数传递给f(指向int的指针)。然后 f 会将参数(这是堆栈上的临时变量)设置为地址 1(这不会导致问题)并返回 1。由于 1 为 true,因此 if () 将继续评估 x == 1,结果为 false ,因为主块中的x仍然是0。if

块的主体不会被执行。

编辑

对于问题的新版本,主体将被执行,因为 f() 返回后,调用块中的 x 为 1。

It will pass the address of the local variable x in the caller block as a parameter to f (pointer to int). f will then set the parameter (which is a temporary variable on the stack) to address 1 (this causes no problem) and return 1. Since 1 is true, the if () will move on to evaluate x == 1 which is false, because x in the main block is still 0.

The body of the if block will not be executed.

EDIT

With your new version of the question, the body will be executed, because after f() has returned, x in the calling block is 1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文