【问题标题】:When run an infintie loop why int or char gives negative value at the end当运行无限循环时,为什么 int 或 char 最后给出负值
【发布时间】:2021-10-28 18:19:55
【问题描述】:
#include <stdio.h>

int main()
{
    signed char x = 0;
    for (; x >= 0; x++);
    printf("%d\n", x);
    return 0;
}

这段代码的输出是-128。谁能解释一下为什么?

【问题讨论】:

  • "...当有符号整数算术运算溢出时(结果不适合结果类型),行为未定义,——可能的表现形式这样的操作包括:..." 见-en.cppreference.com/w/cpp/language/…
  • @Jarod42:这里没有未定义的溢出。行为是实现定义的,而不是未定义的。根据 C 2018 6.5.2.4,x++ 的行为类似于 x += 1。根据 6.5.16.2,x += 1 的行为类似于 x = x+1,除了左值 x 仅计算一次。根据 6.5.16.1,x = x+1 将右侧转换为左侧的类型。根据 6.3.1.3 3,当右侧无法以新类型表示时(例如,当右侧为 128 时,左侧是 8 位二进制补码 signed char),结果要么是实现定义的,要么是引发了实现定义的信号。
  • @molbdnilo:这里没有未定义的行为。见上面的 cmets 和chux’ answer
  • @RichardCritten:在C++中,和在C中一样,操作数被提升为int,加法中没有溢出,总和转换为signed char,结果是实现-已定义。
  • @Jarod42:C 标准要求实现定义转换的行为,这必须是返回实现定义的值或引发实现定义的信号。实现可能未定义转换的行为以导致循环成为无限循环。 C++在这方面也是一样的。

标签: c data-structures char integer


【解决方案1】:

实现定义的行为

signed char x = 0; for (; x &gt;= 0; x++); 迭代 x 从 0 到 127 (SCHAR_MAX),到目前为止一切正常。

在下一次迭代中,x++ 的行为类似于 x = x + 1;,尝试将 128 分配给 signed char x。因为这超出了signed char 范围:

否则,新类型是有符号的,值不能在其中表示;结果要么是实现定义的,要么引发实现定义的信号。
(与转换为有符号类型有关的 C 规范)

一个常见的实现定义的结果是环绕到 -128 或 SCHAR_MIN。可能会发生其他结果,例如分配最大值 127 导致不定式循环。

没有有符号整数溢出,只是超出范围的赋值。


代码的可移植性不高,应避免使用。

【讨论】:

    【解决方案2】:

    这是实现定义的行为。

    在 x86 平台上我都知道编译器,当 x 是 127 并且您添加 1 它执行无符号加法,结果是 0b10000000,其二进制补码有符号整数格式是 -128

    由于x-128,循环终止并打印出-128

    【讨论】:

    • 对了一半。行为是实现定义的。它是由 C 实现定义的,主要是编译器,而不是“平台”。 C 编译器可以提供 C 标准允许的任何行为;他们没有义务盲目地使用指令集。
    猜你喜欢
    • 1970-01-01
    • 2015-01-27
    • 2021-10-28
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 2012-09-02
    • 2021-09-03
    • 1970-01-01
    相关资源
    最近更新 更多