我一直试图围绕整数提升的 C99 规则和整数类型的常用算术转换。在烧掉几个神经元之后,我得出了一套我自己的规则,这些规则要简单得多,但我相信,它相当于官方的:
更新:为了这个问题,我首先定义“物理类型”如下
定义:如果两个整数类型具有相同的大小和符号,则它们是相同的物理类型。
如果你认为这个定义有问题,那么你可能对问题 2 有一个很好的答案。
简化的促销/转换规则
类型排名:在T1和T2两种积分类型中,“最好”的是:
- 以较大者为准
- 如果它们具有相同的大小,以未签名者为准
- 如果它们具有相同的大小和符号,它们中的任何一个,因为它们在物理上是相同的。
积分提升:类型 T 的值应该提升为
提升(T) = 最佳(T, int)
整数类型的常用算术转换:在计算 T1 和 T2 类型的二元运算符之前,应将参数转换为合适的通用类型,即:
共同(T1,T2)=最佳(T1,T2,int)
警告:虽然我相信我的规则给出了正确的物理类型,但在单一类型具有不同名称的情况下,它们可能无法提供正确的类型名称。例如,在系统上int==long
,官方规则说
common(unsigned int, long) = unsigned long
而我的规则说它是unsigned int
(无论如何在物理上是相同的)。但这应该不是问题,因为名称并不重要。还是他们?
在这个漫长的前奏之后,真正的问题来了,它有两个方面:
问题1:我的规则正确吗?
我读了几遍官方的,但我仍然觉得它们令人困惑。因此,我可能误解了一些东西。如果我错了,请提供官方规则和我的规则产生不同类型的示例。我的意思是:不同的物理类型,而不仅仅是物理上相同的不同类型。
一个现实世界的例子将是首选。如果没有找到,如果假设的 C 环境的描述足够详细以令人信服(相关类型的大小等),那么理论上的示例就可以了。
如果我在这里是正确的,那么第二个问题就变得相关了。
问题 2:我为什么要关心提升/转换类型的名称?
如果我是正确的,那么显而易见的问题是“标准委员会的人为什么要编写如此复杂的规则?”。他们唯一的回答是我能想到的,他们不仅要指定促销/转换产生的物理类型,还要指定命名这些类型的正确方法。但是,他们为什么在乎呢?这些类型仅由编译器在内部使用,只要我们了解它们的物理性质,我们如何命名它们并不重要。这个推理有问题吗?您能想到这样一种情况,即 T1 和 T2 在物理上是相同的,但重要的是要知道事物是否会自动升级或转换为 T1 而不是 T2?同样,现实世界的示例将是首选,否则,如果足够详细,理论示例也可以。
基本原理
(部分添加于 2014-11-10,以解决一些评论)
在搜索这些主题时,我总是看到它们在算术运算符行为的上下文中进行讨论,更具体地说,是这些运算符返回的结果。例如,表达式-1L < 1U
是有问题的,因为它在 long 确实比 int 长的系统上为 true,否则为 false。我相信理解这类问题是一件好事,但需要一个复杂的规则集来做到这一点是一件坏事。因此,努力构建一个更简单的规则集,可靠地给出相同的结果。
我完全明白,我的规则对于任何发现真实规则足够简单的人来说都是无用的。我也理解并且恭敬地不同意那些表示依赖官方规则以外的任何东西本质上是不好的观点的人。不过,如果我的规则对除我以外的任何人都有帮助的话,它们还是会有用处的。
关于我个人的偏见:作为一名物理学家,我非常看重简单性。我习惯于处理那些不是——也不应该是——终极真理的理论,但它们被证明是非常有用的,只要你了解它们的适用范围,它们就可以安全使用。在任何给定的情况下,最好的理论都不是最完整的:它是仍然适用的最简单的理论。例如:我不会使用量子引力来计算单摆的周期。我在这里发布这个问题是为了就上述规则的适用范围获得专家意见。
到目前为止,我所拥有的是:
- varargs 案例(坦克,mafso),这似乎是 C99 中这些规则至少在原则上不适用的唯一情况
- 关键字(感谢 Pascal Cuoq) ,
_Generic
作为 C11 功能,稍微超出范围- C++11
auto
关键字,它进一步超出了范围,但有趣的是它会带来(否则不相关的)关于别名规则的担忧。