C 使用纯整数64位会破坏很多合理的代码吗?

C 使用纯整数64位会破坏很多合理的代码吗?,c,64-bit,integer-promotion,C,64 Bit,Integer Promotion,直到最近,我一直认为大多数系统实现者/供应商的决定是一种权宜之计,即使在64位机器上,也要保持纯int32位。对于现代的C99固定大小类型(int32_t和uint32_t等),对每个大小8、16、32和64的标准整数类型的需求基本上消失了,似乎int也可以设置为64位 然而,C中纯int大小的最大实际结果来自这样一个事实,即C基本上没有小于-int类型的算术。特别是,如果int大于32位,则uint32\u t值上的任何算术结果都具有类型符号int,这相当令人不安 在实际实现中,这是将int永

直到最近,我一直认为大多数系统实现者/供应商的决定是一种权宜之计,即使在64位机器上,也要保持纯
int
32位。对于现代的C99固定大小类型(
int32_t
uint32_t
等),对每个大小8、16、32和64的标准整数类型的需求基本上消失了,似乎
int
也可以设置为64位

然而,C中纯
int
大小的最大实际结果来自这样一个事实,即C基本上没有小于-
int
类型的算术。特别是,如果
int
大于32位,则
uint32\u t
值上的任何算术结果都具有类型
符号int
,这相当令人不安

在实际实现中,这是将
int
永久固定为32位的一个好理由吗?我倾向于说是的。在我看来,当
int
大于32位时,
uint32\u t
可能会有大量的用法中断。即使应用一元减运算符或位补运算符也会变得危险,除非您回溯到
uint32\t


当然,同样的问题也适用于当前实现中的
uint16\u t
uint8\u t
,但每个人似乎都知道并习惯于将它们视为“小于-
int
”类型。

好吧,这并不是一个全新的故事。“大多数电脑”我想你指的是台式电脑。已经从16位转换到32位
int
。是否有任何东西表明这次不会发生同样的进展?

“合理的代码”

嗯。。。关于开发的事情是,你编写并修复它,然后它就可以工作了。。。然后你停下来

也许你已经被烧坏了很多,所以你能很好地保持在某些功能的安全范围内,也许你没有被烧坏,所以你没有意识到你依赖的东西可能会有所改变

甚至你依赖于一个bug

在旧的Mac68000编译器上,int为16位,long为32位。但即便如此,大多数现存的C代码都假定int为32,所以在新闻组中找到的典型代码也无法工作。(哦,Mac没有printf,但我离题了。)


所以,我想说的是,是的,如果你改变了什么,那么有些东西就会坏掉。

不特别是。int在某些64位体系结构(不是x64)上是64位的

该标准实际上并不保证获得32位整数,只是(u)int32_t可以保存一个

现在,如果您依赖于int与ptrdiff\t的大小相同,您可能会崩溃

记住,C不能保证机器是二进制机器

具有现代C99固定尺寸类型 (int32和uint32等)需要 因为有一个标准整数 每种尺寸的类型8、16、32和64 大部分都消失了

C99具有固定大小的typedef,而不是固定大小的类型。本机C整数类型仍然是
char
short
int
long
long
。它们仍然相关

ILP64的问题是,它在C类型和C99 typedef之间有很大的不匹配

  • int8_t=char
  • int16\u t=短路
  • int32_t=非标准类型
  • int64_t=int、long或long
发件人:

不幸的是,ILP64模型确实如此 不提供一种自然的方式来描述 32位数据类型,并且必须求助于 不可移植的构造,例如
\uuu int32
来描述此类类型。这可能会造成实际问题 在生成可在上运行的代码时 32位和64位平台都没有
#ifdef
构造。有可能装载大量的货物 无需修改LP64型号的代码 做出这样的改变,而 维持在中国的投资 数据集,即使在 没有提供打字信息 应用程序外部可见


虽然我个人并没有编写这样的代码,但我敢打赌,它在不止一个地方。。。当然,如果您更改
int
的大小,它会断开

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

如果(x&(1)如你所说,我认为提升规则真的是杀手。
uint32\u t
然后会提升到
int
,突然之间,你会有一个几乎所有人都希望无符号的有符号算术

这通常隐藏在只进行算术运算并将其赋值回
uint32\u t
的地方。但在与常量进行比较的地方,这可能是致命的。依赖于此类比较而不进行显式转换的代码是否合理,我不知道。像
(uint32\u t)这样的转换常量1
可能会变得非常乏味。我个人至少总是使用后缀
U
来表示我希望未签名的常量,但这已经不像我希望的那样可读了


还要记住,
uint32\u t
等并不一定存在。甚至连
uint8\u t
都不存在。它的实现是POSIX的一个扩展。因此从这个意义上说,C作为一种语言远远不能做到这一点。

有一种代码习惯用法,如果INT是64位的话,它就会中断,我经常看到它,以至于我认为它是错误的可以说是合理的:

  • 通过测试
    ((val&0x8000000)!=0)
这通常出现在检查错误代码中。许多错误代码标准(如Window的
HRESULT
)使用位31表示错误。代码有时会通过测试位31或检查错误是否为负数来检查错误

微软用于测试HRESULT的宏使用这两种方法——我敢肯定