直到最近,我还考虑了大多数系统实施者/供应商的决定 int 即使在64位机器上,也有32位。现代C99固定尺寸类型(int32_tuint32_t, ,等等。 int 也可以制作64位。

但是,平原大小的最大实际结果 int 在C中,C来自C的事实,即C基本上没有算术的算术。int 类型。特别是 int 大于32位,这是任何算术的结果 uint32_t 值具有类型 signed int, ,这是令人不安的。

这是保留的好理由吗 int 永久固定在现实世界实施的32位?我倾向于说是的。在我看来,可能有大量的用途 uint32_t 什么时候突破 int 大于32位。即使应用一单位负或位相互作用的操作员也变得危险,除非您归还 uint32_t.

当然,同样的问题适用于 uint16_tuint8_t 在当前的实施方面,但每个人似乎都意识到并用来将它们视为“比人小得多int“类型。

有帮助吗?

解决方案

正如您所说,我认为晋升规则确实是杀手。 uint32_t 然后会促进 int 突然之间,您签署了算术,几乎每个人都期望未签名。

这主要隐藏在您只做算术并分配回到一个的地方 uint32_t. 。但是,在您与常数进行比较的地方,这可能是致命的。我不知道,是否依赖于此类比较的代码是否合理。铸造常数喜欢 (uint32_t)1 可能会变得非常乏味。我个人至少总是使用后缀 U 对于我想被签名的常数,但这已经不像我想要的那样可读。

还要记住 uint32_t 等等不能保证存在。甚至不 uint8_t. 。执行是Posix的扩展。因此,从这个意义上说,C作为一种语言远非能够采取这种举动。

其他提示

“合理的代码” ...

好吧...关于开发的事情是,您编写和修复它,然后它起作用...然后您停下来!

也许您被烧毁了很多,所以您在某些功能的安全范围内保持良好 那种特殊的方式 因此,您没有意识到自己依靠可能改变的东西。

甚至您要依靠错误。

在Olden Mac 68000编译器上,INT为16位,长为32。但是即使如此,大多数现存的C代码都认为INT是32,因此您在新闻组上发现的典型代码也无法正常工作。 (哦,Mac没有printf,但是我离题了。)

所以,我想到的是,是的,如果您更改 任何事物, ,那么有些事情就会破裂。

使用现代C99固定尺寸类型(INT32_T和UINT32_T等),需要每个大小8、16、32和64的标准整数类型,大多数消失,

C99具有固定尺寸的Typedefs,而不是固定尺寸类型。本机C整数类型仍然 char, short, int, long, , 和 long long. 。他们仍然很重要。

ILP64的问题在于它在C类型和C99 Typedefs之间具有很大的不匹配。

  • int8_t = char
  • int16_t =短
  • int32_t = 非标准类型
  • int64_t = int,长或长长

64位编程模型:为什么要LP64?:

不幸的是,ILP64模型没有提供描述32位数据类型的自然方法,并且必须诉诸于不可便捷的构造,例如 __int32 描述这种类型。这可能会在生产代码中引起实际问题,该代码可以在32位和64位平台上运行 #ifdef 构造。即使在应用程序未能通过外部可见的情况下,即使在数据集中进行投资,也可以将大量代码移植到LP64型号的情况下,而无需进行此类更改,同时维护数据集进行的投资。

DEC Alpha和OSF/1 Unix是UNIX的第一个64位版本之一,它使用了64位整数-ILP64架构(含义 int, long 指针均为64位)。它引起了很多问题。

我没有看过的一个问题 - 这就是为什么我这么长时间后回答的原因是,如果您有64位 int, ,您使用什么尺寸 short?两位16位(经典,什么都不改变的方法)和32位(激进的'好吧,一个 short 应该是一半 int'方法)将带来一些问题。

与C99 <stdint.h><inttypes.h> 标题,您可以为固定尺寸整数编码 - 如果您选择忽略36位或60位整数的机器(至少是准立场)。但是,大多数代码不是使用这些类型编写的,并且通常存在深度座位的,并且在代码中基本上隐藏了(但从根本上是有缺陷的)假设,如果该模型与现有变体不同,则会不满意。

注意Microsoft的64位窗口的超保守LLP64型号。之所以选择这是因为如果更改了32位模型,则太多旧的代码会破坏。但是,由于差异,已移植到ILP64或LP64架构的代码无法立即移植到LLP64上。阴谋理论家可能会说是故意选择的,以使为64位Unix编写的代码更难移植到64位窗口。在实践中,我怀疑这不仅仅是对微软的副作用的快乐。也必须对32位Windows代码进行大量修订以利用LP64型号。

如果INT为64位,就会有一个代码习惯,我经常看到它可以称为合理:

  • 检查值是否通过测试是否为负 ((val & 0x80000000) != 0)

这通常在检查错误代码中找到。许多错误代码标准(例如Window的 HRESULT)使用位31表示错误。和代码有时会通过测试位31或有时检查错误是否为负数来检查该错误。

微软测试Hresult的宏都使用两种方法 - 我敢肯定,那里有很多代码在不使用SDK宏的情况下进行类似的代码。如果MS已移至ILP64,这将是一个导致llp64型号(或LP64型号)完全避免的移植头痛的区域。

注意:如果您不熟悉诸如“ ILP64”之类的术语,请在答案结束时查看Mini-Glossary。

我敢肯定,假设这些INT的大小为32位,则使用纯老式的INT来容纳错误代码(不一定是面向Windows的)。我敢打赌,该错误状态方案有很多代码,也使用两种检查(< 0 并设置了位31),如果移至ILP64平台,它将突破。如果仔细构造了错误代码,可以进行这些检查以继续正确工作,以便进行签名,但是再次,我看到的许多这样的系统通过将BITFIELD组合在一起来构建错误值。

无论如何,我认为这绝不是一个无法解决的问题,但我确实认为这是一种相当普遍的编码实践,如果搬到ILP64平台,则会导致很多代码需要修复。

请注意,我也不认为这是Microsoft选择LLP64模型的最大原因之一(我认为该决定在很大程度上是由32位和64位流程之间的二进制数据兼容性驱动的,因为 在MSDN中提到在雷蒙德·陈的博客上).


迷你辉煌 对于64位平台编程模型术语:

  • ILP64: int, long, ,指针是64位
  • LP64: long 指针是64位, int 是否有32位(大多数(最多)Unix平台使用)
  • LLP64: long long 指针是64位, intlong 保持32位(在Win64上使用)

有关64位编程模型的更多信息,请参见 “ 64位编程模型:为什么要LP64?”

虽然我个人不这样写代码,但我敢打赌,它在一个以上的地方存在...当然,如果您更改大小 int.

int i, x = getInput();
for (i = 0; i < 32; i++)
{
    if (x & (1 << i))
    {
        //Do something
    }
}

好吧,这并不是这个故事是全新的。使用“大多数计算机”,我认为您的意思是台式计算机。已经有从16位到32位的过渡 int. 。这次没有什么表明相同进展不会发生的东西吗?

不是特别。 INT在大约64位体系结构上为64位(不是X64)。

该标准实际上不能保证您获得32位整数,只是(u)int32_t可以容纳一个整数。

现在,如果您根据int的大小与ptrdiff_t相同,则可能会被打破。

请记住,C不能保证机器甚至是二进制机器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top