https://en.cppreference.com/w/c/language/eval_order
在C11之前,你必须遵守规则(2)
There is a sequence point after evaluation of the first (left) operand and
before evaluation of the second (right) operand of the following binary
operators: && (logical AND), || (logical OR), and , (comma).
因为参数在 C11 之前被认为是用逗号分隔的。这不是最优的,因为参数在某些平台上是从右向左推送的。因此,C11 添加了规则 (12) 使其未指定。
A function call that is not sequenced before or sequenced after another
function call is indeterminately sequenced (CPU instructions that
constitute different function calls cannot be interleaved, even if the
functions are inlined)
即使是 C99 指定的初始值设定项,仍然会回到规则 (2),其中相对于逗号运算符,较早(左)的初始值设定项在较晚(右)的初始值设定项之前被解析。也就是说,直到 C11 添加规则 (13) 使其未指定。
In initialization list expressions, all evaluations are indeterminately
sequenced
换句话说,在规则 (12) 和规则 (13) 之前,规则 (2) 中的逗号运算符是指定的行为。规则 (2) 导致无法在某些平台上优化的低效代码。如果结构成员或函数参数的数量超过某个阈值,则没有足够的寄存器。也就是说,“注册压力”成为一个问题。
从历史上看,聚合类型初始值设定项和函数参数回退到逗号运算符。在 C11 中,他们特别添加了在这些聚合类型初始化程序和函数参数中的逗号不是“逗号运算符”的定义,因此规则 (12) 和规则 (13) 有意义,并且规则 (2) 不适用。