对某些函数使用增量运算符

Using increment operators with some functions

本文关键字:运算符 函数      更新时间:2023-10-16

如果我做这样的事情:

static int counter = 0;
counter = std::min(8, counter++);

我收到 g++ 的警告说:

operation on 'counter' may be undefined [-Wsequence-point]

这工作正常:

static int counter = 0;
counter++;
counter = std::min(8, counter);

结果与++counter和/或std::max相同。

我无法弄清楚第一个版本有什么问题。std::max 也会发生这种情况。仅举个例子,我在使用 GLM 的函数时没有收到任何警告。

谁能为我解释一下?我在 Ubuntu 4.8 上使用 GCC 14.04。

编辑:更多的测试(我应该先做)如果我做cntr = std::min(8, ++cntr);,就像我在实际应用程序中一样,打印此行之后的值会导致 1,然后是 2,然后是 3,依此类推,但是,如果我cntr = std::min(8, cntr++);,则每次的 vaule 都是 0,它永远不会增加。

我认为迈克·西摩的评论是正确的 - 不应该有 UB,因为函数参数表达式应该在函数调用之前排序。从 1.19/15:

调用函数(无论该函数是否为内联函数)时,与任何参数表达式或指定被调用函数的后缀表达式关联的每个值计算和副作用都会在执行被调用函数主体中的每个表达式或语句之前进行排序。

所以 gcc 可能是不正确的。另请注意,在其他一些情况下,警告不会显示:

int f(int a, int b);
template <typename T> T g(T a, T b);
template <typename T> const T& h(const T& a, const T& b);
counter = f(8, counter++); // no warning
counter = g(8, counter++); // no warning
counter = h(8, counter++); // gcc gives warning - there should be nothing special
                           // about h as compared to f,g... so warning is likely
                           // incorrect

Clang没有对这些警告。

鉴于函数参数在调用之前是有序的,这就解释了为什么:

int counter = 0;
counter = std::min(8, counter++);

始终返回 0。该代码等效于:

counter = 0;
int a1 = 8;         // these two can be evaluated in either order
int a2 = counter++; // either way, a2 == 0, counter == 1
counter = std::min(a1, a2); // which is min(8, 0) == 0.