整数转换(缩小,扩展),未定义的行为

时间:2013-10-09 13:35:56

标签: c integer type-conversion implicit-conversion

我很难以我能够轻易理解的方式找到有关此主题的信息,因此我要求对我所发现的内容进行审核。这只是关于转换和转换的内容。
< / p>


在示例中,我将指的是:

(signed/unsigned) int bigger;
(signed/unsigned) char smaller;
  1. 截断整数。 (超大化&GT;小)

    • 首先截断 bigger MSB 一侧以匹配smaller尺寸。
    • 第二,截断结果转换为已签名/未签名,具体取决于较小的类型。


    如果较大的值太大而不适合较小的类型,则会导致未定义的行为(纠正我)。但是我的规则应该适用于所有机器(在此也纠正我),结果应该是可预测的。

  2. 加宽整数(较小 - >较大)

    a)signed char - &gt; signed int

    • 使用MSB(1或0)前置较小以匹配较大的尺寸
    • 转换为签名

    b)signed char - &gt; unsigned int

    • 使用MSB(1或0)预先缩小以匹配更大的尺寸。
    • 转换为无符号

    c)unsigned char - &gt; signed int

    • 前缀为0以匹配更大的尺寸
    • 转换为签名

    d)unsigned char - &gt; unsigned int

    • 前缀为0以匹配更大的尺寸
    • 转换为无符号
  3. 我没有提到可能弹出的未定义/未指定的行为在哪里?

2 个答案:

答案 0 :(得分:18)

积分转换永远不会产生未定义的行为(它可以产生实现定义的行为)。

转换为可以表示转换值的类型始终是明确定义的:值只是保持不变。

转换为无符号类型始终是明确定义的:以UINT_MAX + 1(或目标类型允许的任何最大值)为模取值。

转换为无法表示正在转换的值的带符号类型会导致实现定义的值或实现定义的信号。

请注意,上述规则是根据整数值定义的,而不是根据位序列定义的。

答案 1 :(得分:1)

来自C标准文件(p.50草案版本201x我相信而不是确切的引用):

  • 没有两个有符号整数具有相同的等级

  • 有符号整数的等级应大于精度较低的任何有符号整数的等级。

  • long long int大于long int,大于int,大于short int,大于short int。

  • 相同精度的有符号和无符号具有相同的等级(例如:signed int与unsigned int相同)

  • 任何标准整数类型的等级应大于任何相同宽度的扩展整数类型的等级。

  • char的等级等于unsigned char等于signed char。

(因为你把它们从你的问题中排除在外,我正在抛弃bool)

  • 任何扩展有符号整数相对于另一个扩展有符号整数的等级是实现定义的,但仍受其他整数转换等级规则的约束。

  • 对于所有整数类型T1 T2和T3,T1的等级大于T2,T2的等级大于T3,而T1的等级大于T3。

具有整数类型(int和signed int除外)的对象,其整数等级小于或等于int和unsigned int的等级,类型为_Bool,int,signed int或unsigned int的位字段;如果int可以表示原始类型的所有值,则该值将转换为int。否则为unsigned int。所有其他类型都由整数提升更改。

简单来说:

当转换为其他类型的更高级别时,任何比int或unsigned int“小”的类型都会被提升为int。这是编译器的工作,以确保为给定机器(体系结构)编译的C代码在这方面符合ISO-C。 char是实现定义的(被签名或未签名)。所有其他类型(促销或“降级”)都是实现定义的。

什么是实现定义?这意味着给定的编译器将在给定的机器上系统地表现相同。换句话说,所有“实现定义的”行为都取决于编译器和目标机器。

制作便携式代码:

  • 始终将价值提升到更高级别的标准C类型。
  • 永远不要将值降级为较小的类型。
  • 避免代码中的所有“实现定义”实现。

如果它破坏程序员的努力,为什么存在实现定义的疯狂?系统编程基本上需要这些实现定义的行为。

更具体地针对您的问题:

  • 截断很可能不会成为可能。或者在维护,错误跟踪等方面需要更多的努力,而不仅仅是通过使用更高级别的类型来维护代码。
  • 如果您的实现运行的值大于所涉及的类型,则您的设计是错误的(除非您参与系统编程)。
  • 根据经验,从无符号到签名保留值但不是相反。因此,当一个无符号值与一个有符号值相对应时,将unsigned提升为signed而不是相反。
  • 如果在您的应用程序中使用尽可能小的整数类型对内存至关重要,那么您应该重新审视整个程序的架构。