15

我很难以我容易理解的方式找到关于这个主题的信息,所以我要求对我发现的内容进行审查。这完全是关于转换和转换的。


在示例中,我将参考:

(signed/unsigned) int bigger;
(signed/unsigned) char smaller;
  1. 截断整数。(更大->更小)

    • 首先在MSB端截断 以匹配大小。biggersmaller
    • 其次,根据较小的类型截断的结果转换为有符号/无符号。


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

  2. 扩大整数(更小->更大)

    一)signed char->signed int

    • 在更小的前面加上 MSB(1 或 0)以匹配更大的大小
    • 转换为签名

    b)signed char->unsigned int

    • 在更小的前面加上 MSB(1 或 0)以匹配更大的大小。
    • 转换为无符号

    c) unsigned char->signed int

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

    d) unsigned char->unsigned int

    • 前面加 0 以匹配更大的尺寸
    • 转换为无符号

我没有提到的未定义/未指定的行为会在哪里弹出?

4

2 回答 2

23

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

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

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

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

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

于 2013-10-09T14:14:39.037 回答
1

来自 C 标准文档(我相信第 50 页草稿版本 201x,而不是准确引用):

  • 没有两个有符号整数的秩相同

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

  • long long int 大于 long int 大于 int 大于 short int 大于signed char。

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

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

  • 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。否则为无符号整数。整数提升会更改所有其他类型。

简单来说:

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

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

制作可移植代码:

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

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

所以更具体地说是针对您的问题:

  • 截断很可能是不可转移的。或者将需要在维护、错误跟踪等方面付出更多的努力,而不是简单地使用更高级别的类型来维护代码。
  • 如果您的实现运行的值大于所涉及的类型,则您的设计是错误的(除非您参与系统编程)。
  • 根据经验,从无符号到有符号会保留值,但反之则不然。因此,当一个无符号值与一个有符号值并驾齐驱时,将无符号值提升为有符号值,而不是相反。
  • 如果在您的应用程序中使用尽可能小的整数类型对内存至关重要,那么您可能应该重新审视整个程序的架构。
于 2013-10-09T14:07:24.603 回答