【问题标题】:Wrap-up of values of type ints and chars整数和字符类型值的总结
【发布时间】:2022-01-29 13:10:37
【问题描述】:

我们知道 char 变量的范围是从 -128 到 127,最大值是 255(在 unsigned char 的情况下)。所以请清除我的以下疑问:

  1. char c=255; 因为它超出了范围,为什么它包装 255 而不是给出错误?

  2. 为什么没有负 char 值(-128 到 -1)的 ascii 值?比如 0-9 的 48-57(字符值)

  3. 当我们执行int x=4*1024*1024*1024; 时,会出现溢出错误,但是, 当我们执行int x=4 * 1024; x*=(1024*1024); 时,它(编译器)不会给出错误,而是进行换行。为什么?

【问题讨论】:

    标签: c++ c char


    【解决方案1】:

    我们知道 char 变量的范围是 -128 到 127,最大值是 255(在 unsigned char 的情况下)

    C 标准要求 unsigned char 的范围至少为 0 到 255。您可以为 unsigned char 制作一个具有更大范围的 C 实现,使其超过八位。

    char 可以有符号(范围至少为 -127 到 +127)或无符号。

    1.)char c=255;// 既然超出了范围,那么为什么它把 255 包裹起来而不是报错呢??

    C 标准中的规则是,如果 255 超出 char 的范围,则 255 将以实现定义的方式转换为 char 的类型。因此每个 C 实现都可以定义自己的转换规则。

    编译器可以超越 C 标准并为此发出警告。如果您在编译器中启用其他警告,它可能会这样做。

    2.)为什么没有负字符值的ascii值**(-128到-1)**??比如 48-57 代表 0-9(字符值)

    这就像问为什么我的购物清单上只有七件商品。没有更多,因为我没有在列表中添加更多内容。 ASCII 委员会只定义了代码 0 到 127 的字符。ASCII 中没有更多的代码,因为委员会没有定义更多。他们正在努力将字符放入七位,留下八分之一(通常是八字节字节)用于奇偶校验或其他目的。

    3.)当我们执行 int x=4102410241024;它给出了溢出错误但是,当我们执行 int x=4 * 1024; x=(1024*1024);它(编译器)不给出错误,而是进行包装。为什么?

    当询问错误消息时,您应该提供错误消息的确切文本。我不知道你的编译器给了你哪个“溢出错误”,但它可能会警告你右操作数大于左操作数可以表示的类型。使用常量,编译器很容易看到值太大并给出警告。对于涉及运算符的表达式,编译器需要做更多的工作才能看到结果太大并给你一个警告。如果在编译时计算表达式的值不是太难的话,一些编译器会这样做。

    C 标准未定义溢出操作的结果。像上面这样的转换需要实现定义,但是如果你做一个溢出的乘法,实现不需要定义行为。一些 C 实现可能会定义要包装的算法,但它们不是必须这样做的。

    【讨论】:

      【解决方案2】:

      编程就是关于规则——遵循它们,或者至少知道它们是什么。

      其中一条规则是,有时没有规则。

      我们知道 char 变量的范围是 -128 到 127,最大值是 255(在 unsigned char 的情况下)

      嗯,实际上,不,我们不知道。实际规则是signed char 的范围是从 至少 -127 到 +127(但在某些系统上可能更多),unsigned char 的范围至少是 0到 255(但可能更多),并且纯 char 的类型可能是有符号的或无符号的。

      还有另一条规则说,在大多数情况下,溢出的行为是没有完全定义的(通常是正式的undefined),这意味着,在某些情况下,在这种情况下,编译器可以为所欲为,甚至不必保持一致。 (这就是我说“规则之一是,有时没有规则”时的意思。)

      所以当你写的时候

      char c = 255;
      

      可能是您机器上的纯 char 未签名(在这种情况下根本没有溢出),或者可能是这样的情况,尽管存在溢出,但您的编译器决定不抱怨它。

      为什么没有负字符值的ascii值**(-128到-1)**??

      因为原来的 ASCII 是一个 7 位代码。在那些日子里,第八位通常是parity bit,这意味着你只有 7 个真正的位可以玩。最终,确实出现了其他 128 个值(具有第 8 位集的值)的定义,最流行的是 ISO 8859 集,以及各种 MS-DOSWindowsMacintosh 字符集。但是,对于任何 8 位字符集,“扩展”字符是对应于值 128 — 255 还是对应于值 -1 — -128 并不总是很清楚。 (这与以下事实有关,同样,普通的 char 可以签名或未签名。)

      3.)当我们做 int x=4*1024*1024*1024;它给出了溢出错误但是,当我们做 int x=4 * 1024; x*=(1024*1024);它(编译器)不给出错误,而是进行包装。为什么?

      这就是我之前所说的“在某些情况下,编译器可以为所欲为,甚至不必保持一致”的意思。一些编译器确实会尝试警告整数溢出,但有时他们的尝试看起来相当半心半意。有关此案例的更多信息,请参阅 Eric Postpischil 的回答。

      【讨论】:

      • char c = 255; 没有溢出,并且行为不是未定义的。如果 255 在 char 中不可表示,则根据 C 2018 6.3.1.3 3,行为是实现定义的。
      猜你喜欢
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 2016-02-18
      • 2014-06-30
      相关资源
      最近更新 更多