为什么会-LLONG_MIN
导致未定义的行为?
C11,6.5.3.3p3:
一元 - 运算符的结果是其(提升的)操作数的负数。对操作数执行整数提升,结果具有提升后的类型。
这里我们看到C标准并不要求实现一元-运算符,例如使用按位-不后跟加1,其中“加1”可能会导致未定义的行为。
如何从导致未定义行为的引用文本中推断出来-LLONG_MIN
?
为什么会-LLONG_MIN
导致未定义的行为?
C11,6.5.3.3p3:
一元 - 运算符的结果是其(提升的)操作数的负数。对操作数执行整数提升,结果具有提升后的类型。
这里我们看到C标准并不要求实现一元-运算符,例如使用按位-不后跟加1,其中“加1”可能会导致未定义的行为。
如何从导致未定义行为的引用文本中推断出来-LLONG_MIN
?
仅从引用的文本中无法推断出这一点。然而,这一连串的推理就足够了:
LLONG_MIN
为 -9,223,372,036,854,775,808,而LLONG_MAX
为 9,223,372,036,854,775,807 (C 2018 5.2.4.2.1 1)。LLONG_MIN
和LLONG_MAX
具有这些值。(我假设读者熟悉二进制补码,并且该标准允许二进制补码。)-LLONG_MIN
将为 9,223,372,036,854,775,808 (C 2018 6.5.3.3 3)。LLONG_MIN
为long long int
(C 2018 5.2.4.2.1 1),结果的类型-LLONG_MIN
为long long int
(C 2018 6.5.3.3 3 and 6.3.1.1)。long long int
的含义)表示。LLONG_MIN
LLONG_MAX
从引用的文本中不可能推断出它。您还需要此文本https://port70.net/~nsz/c/c11/n1570.html#6.5p5:
在 的数学结果
-LLONG_MIN
无法用long long
类型表示的实现中,会触发此规则并且行为未定义。正如其他答案所指出的,这种情况由第 6.5-5 段涵盖,其中表示如果结果不能用其类型表示,则行为是未定义的。
一般来说,未定义的行为可能是在 C 标准中根本没有定义(提及)该行为的情况,但在这种情况下,标准是相当明确的。
当涉及到有符号整数类型时,C18 标准(及更早版本)允许 3 种表示形式(第 6.2.6.2-2 段)
使用“补码”表示时,最小可表示值的负值是不可表示的(它将比最大可表示值大一)。
通过“符号和大小”和“补码”,最小可表示值的负值是可表示的(它将等于最大可表示值)。
因此,
-LLONG_MIN
当且仅当实现使用“二进制补码”表示时,才是未定义的行为。由于标准因此允许未定义行为的实现,因此该行为在标准方面是未定义的。
在标准未定义行为的情况下,始终允许实现定义行为,但在这种情况下,标准明确描述了一组具有已定义行为的实现
-LLONG_MIN
(不使用带符号整数的补码表示形式) 。可以通过静态断言来检查实现是否具有
-LLONG_MAX==LLONG_MIN
,但它几乎没有实际用途,因为二进制补码表示是迄今为止最常见的。即将推出的 C2x 标准将仅允许二进制补码表示(第 6.2.6.2-2 段)。因此,对于 C2x,
-LLONG_MIN
根据标准而言,始终是未定义的行为。