【问题标题】:C assigning values greater than data type rangesC 赋值大于数据类型范围
【发布时间】:2015-07-10 18:07:52
【问题描述】:

C int type中可以有以下+ve的取值范围2,147,483,647

来源https://msdn.microsoft.com/en-IN/library/s3f49ktz.aspx

我想知道如果我分配的值大于 int 可以容纳的值会发生什么,如果我这样做了,这些值是如何截断的或者确切存储了什么

int var=2147483648;

【问题讨论】:

  • signed 类型会导致整数溢出。
  • 知道违反规则时会发生什么通常没什么用,除非规范说明会发生什么。大多数情况下,唯一的结果是“未定义的行为”(缩写为 UB)。 UB 在一个系统上的样子不一定是在另一个系统上的样子,甚至在参数发生某些变化(通常是不可预测的)时也一样。

标签: c int range


【解决方案1】:
int var = 2147483648;

有符号整数的实际行为是实现定义的。该值很可能会缩小(换句话说,“截断”)到四个最低有效字节(假设sizeof(int) = 4)。

常量2147483648 可能是long 类型(或者long long,如果前者不足以容纳它),所以这里实际发生的情况是这样的:

int var = (int) 2147483648LL;

转换后的实际值为-2147483648,因为只设置了符号位(假设二进制补码表示)。

引用 C11 (N1570) §6.3.1.3/p3 有符号和无符号整数(强调我的):

否则,新类型有符号,值无法表示 在里面;结果要么是实现定义的,要么是 引发了实现定义的信号。

例如,使用GCC,结果是减少结果模2^N,这实际上与字节“截断”相同:

为了转换为宽度为 N 的类型,值以 2^N 为模减少 在类型的范围内;没有发出信号。

【讨论】:

  • 是的,我正在使用 gcc,并且值正在以某种循环方式映射..我也想在其他机器上检查一下。
  • @FalconZex:只是一个非常善意的建议:不要依赖这个。没有获得调查非标准行为的知识。专心写干净的代码,世界上的废话/坏代码已经够多了。
  • @Olaf:考虑short a = 0x40f2; a <<= 3; printf("%hd", a)。您认为此代码是“废话/损坏”吗? (即整数提升到int“幕后”)。底层机制其实和上面是一样的。我并不是说应该依赖这一点,但实现定义与 UB 不同,至少实现必须记录它。
  • 很公平。前提是它有据可查并且在要移植的代码中非常小心地使用(我应该有更多的区别),但不是因为 OP 似乎使用它。一般来说,如果有符号类型没有足够小的值来保留符号,那么转换它们很少是一个好主意。我主要从事嵌入式编程,并且有意使用大多数无符号类型。
  • @FalconZex:正如我在回答中所写,unsigned 整数具有明确定义的溢出行为(包装);您可能会考虑使用它们而不是单独的值。
【解决方案2】:

正如您引用的链接语句,它是错误。但是,链接页面正确表明它对该特定实现有效。阅读standard 了解标准类型的最小范围

实际尺寸为limits.h。你不应该依赖其他任何东西。如果您需要特定大小,请使用stdint.h 类型。

如果您将带符号的值分配给无法保存该值的对象,则结果为implementation defined。 适当的编译器允许对此类问题启用警告 - 使用它们!

OTOH,对于无符号值,它的定义非常明确(标准的同一部分)。简单来说就是忽略高位。

【讨论】:

  • 从技术上讲,引用的陈述并没有错,这只是一个编译器实现标准的方式。
  • @ThePcLuddite:谢谢!已编辑。
  • 我提到的尺寸与limits.h中提到的相似
  • @FalconZex:问题是,您说“In C int type ...”,但这仅适用于您的(可能还有其他一些)实现,通常不适用于C。其他实现可能有不同的限制(例如,对于 8/16 位 CPU)。因此,我强烈建议使用这些库。两者都必须由任何 C 编译器提供。一切都在标准中;真的值得一看(而且阅读 imo 并不复杂)。
【解决方案3】:

通常,如果类型在源代码中初始化,如您的示例所示,您可能会收到编译器警告或错误。编译为可能的最高警告级别。

如果溢出是计算的结果,它将是未定义的。在实践中,这会导致回绕或截断,可能会出现溢出错误。

【讨论】:

    【解决方案4】:

    在 C 中,没有溢出检查。结果是实现定义

    【讨论】:

    • @Olaf 我修正了答案。
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 2012-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多