C语言 为什么-LLONG_MIN会导致未定义的行为?

xpcnnkqh  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(146)

为什么-LLONG_MIN会导致未定义的行为?
C11,6.5.3.3p3:
一元运算符的结果是其(提升)操作数的负数。整数提升是在操作数上执行的,结果具有提升类型。
这里我们看到C标准不要求实现一元运算符-,例如,使用按位-not后跟adding 1,其中“adding 1”可能会导致未定义的行为。
如何从引用的文本中推断出-LLONG_MIN导致未定义的行为?

zwghvu4y

zwghvu4y1#

如何从引用的文本中推断-LLONG_MIN导致未定义的行为?
单从引文中是无法推断出这一点的,然而,这一系列的推理就足够了:

  • C标准允许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)。
  • 存在(在数学意义上)一个C实现,其中LLONG_MINLLONG_MAX具有这些值。(我假设读者熟悉2的补码,并且标准允许2的补码。)
  • 在这样的C实现中,-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和6.3.1.1)。
  • 在上述C实现中,该值不能用long long int表示(由于LLONG_MINLLONG_MAX的含义)。
  • C 6.5 5说:

如果在表达式求值过程中出现 exceptional condition(即,如果结果没有数学定义或不在其类型的可表示值范围内),则行为未定义。

nwlls2ji

nwlls2ji2#

如何从引用的文本中推断出-LLONG_MIN导致未定义的行为?
这是不可能推断出它从引用的文本.你还需要这个文本https://port70.net/~nsz/c/c11/n1570.html#6.5p5:
如果在表达式求值过程中出现异常条件(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则行为未定义。
-LLONG_MIN的数学结果不能用long long类型表示的实现中,此规则被触发,行为未定义。

6ioyuze2

6ioyuze23#

正如其他答案所指出的那样,这种情况在6.5-5段中有所涉及,该段说,如果结果不能由其类型表示,则行为是未定义的。
一般来说,未定义的行为可能是C标准中没有定义(提到)的行为,但在这种情况下,标准是非常明确的。
当涉及到有符号整数类型时,C18标准(及更早版本)允许3种表示(第6.2.6.2-2节)

  • 符号和幅度
  • 二进制补码
  • 一补数

在“二补数”表示中,最小可表示值的负值是不可表示的(它将比最大可表示值多一个)。
用“符号和大小”和“一个的补数”,最小可表示值的负值是可表示的(它将等于最大可表示值)。
因此,-LLONG_MIN是未定义的行为,当且仅当实现使用“二进制补码”表示时。
由于该标准因此允许实现这是未定义的行为,因此该行为在该标准中是未定义的。
在标准未定义行为的情况下,总是允许实现定义行为,但在这种情况下,标准明确地描述了一组具有-LLONG_MIN定义行为的实现(那些不使用带符号整数的二进制补码表示的实现)。
如果实现有-LLONG_MAX==LLONG_MIN,可以通过静态Assert来检查,但它几乎没有实际用途,因为2的补码表示是目前最常见的。
即将到来的C2 x标准将只允许2的补码表示(第6.2.6.2-2节)。因此,对于C2 x,-LLONG_MIN将始终是标准中未定义的行为。

相关问题