在C中,当操作数的符号不匹配时,增强赋值运算符的行为如何?

huangapple go评论66阅读模式
英文:

How do the augmented assignment operators in C behave when the signedness of the operands do not match?

问题

I have seen a similar question but mine is specifically referring to the augmented assignment operators such as +=, -=, etc. How exactly do the those operators work when I have the following?

extern signed s;
extern unsigned u;
s += u;

Will this be equivalent to this?

s = (signed)((unsigned)s+u);

More specifically would this invoke undefined behavior due to signed integer overflow?

signed s = INT_MAX;
unsigned u = 1;
s += u;

I am aware that when using the normal arithmetic operators, the unsigned type usually dominates. However, I am not sure if this holds true for the augmented assignment operators.

英文:

I have seen a similar question but mine is specifically referring to the augmented assignment operators such as +=, -=, etc. How exactly do the those operators work when I have the following?

extern signed s;
extern unsigned u;
s += u;

Will this be equivalent to this?

s = (signed)((unsigned)s+u);

More specifically would this invoke undefined behavior due to signed integer overflow?

signed s = INT_MAX;
unsigned u = 1;
s += u;

I am aware that when using the normal arithmetic operators, the unsigned type usually dominates. However, I am not sure if this holds true for the augmented assignment operators.

答案1

得分: 3

这段代码的翻译如下:

这个:

    s += u;

与这个相同:

    s = s + u;

根据[C标准](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)的第6.5.16.2p3节:

> 形式为 `E1 op = E2` 的复合赋值等同于简单的赋值表达式 `E1 = E1 op (E2)`,只是 lvalue `E1` 仅被评估一次,并且在不确定序列的函数调用方面,复合赋值的操作是单次评估。

所以首先评估 `s + u`。这导致 `s` 转换为 `unsigned` 类型,按照通常的算术转换,结果是无符号的。然后将此结果赋回给 `s`,它经历了从 `unsigned` 到 `signed` 的转换。

所以在这个特定情况下:

    signed s = INT_MAX;
    unsigned u = 1;
    s += u;

`s` 的值转换为 `unsigned` 并添加了 1,结果是 `INT_MAX + 1` 的无符号值。然后将此值转换为 `signed`,由于该值超出范围,根据第6.3.1.3p3节,会发生一个实现定义的转换:

> *1* 当具有整数类型的值转换为另一整数类型而不是 _Bool 时,如果该值可以由新类型表示,它将保持不变。
> 
> *2* 否则,如果新类型是无符号的,则通过重复添加或减去一个超出新类型表示范围的最大值加一的值,直到该值在新类型的范围内,进行转换。
> 
> *3* **否则,新类型是有符号的,而值无法表示在其中;结果要么是实现定义的,要么引发实现定义的信号。**

因此,上述代码没有未定义的行为,但具有实现定义的行为。

<details>
<summary>英文:</summary>

This:

    s += u;

Is the same as this:

    s = s + u;

As per section 6.5.16.2p3 of the [C standard](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):

&gt; A compound assignment of the form `E1 op = E2` is equivalent to the
&gt; simple assignment expression `E1 = E1 op (E2)`, except that the lvalue
&gt; `E1` is evaluated only once, and with respect to an
&gt; indeterminately-sequenced function call, the operation of a compound
&gt; assignment is a single evaluation

So first `s + u` is evaluated.  This causes `s` to be converted to type `unsigned` as per the usual arithmetic conversions, and the result is unsigned.  Then this result is assigned back to `s` which undergoes a conversion from `unsigned` to `signed`.

So in this particular case:

    signed s = INT_MAX;
    unsigned u = 1;
    s += u;

The value of `s` is converted to `unsigned` and 1 is added to it, resulting in an unsigned value of `INT_MAX + 1`.  This value is then converted to `signed`, which undergoes an implementation defined conversion due to the value being out of range as per section 6.3.1.3p3:

&gt; *1* When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new
&gt; type, it is unchanged.
&gt; 
&gt; *2* Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that
&gt; can be represented in the new type until the value is in the range of
&gt; the new type.
&gt; 
&gt; *3* **Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an
&gt; implementation-defined signal is raised.**

So the above does not have undefined behavior, but it does have implementation defined behavior.

</details>



huangapple
  • 本文由 发表于 2023年5月7日 01:55:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190341.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定