首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >什么ABI限制了[u]intmax_t的大小?

什么ABI限制了[u]intmax_t的大小?
EN

Stack Overflow用户
提问于 2015-04-29 02:51:16
回答 3查看 1.1K关注 0票数 22

从1999年版本开始,ISO标准定义了一个标准头<stdint.h>,其中定义了typedefs intmax_tuintmax_t。它们分别指定“能够表示任何(有符号|无符号)整数类型的任何值的(有符号|无符号)整数类型”。

例如,通常情况下,如果最宽的带符号和无符号整数类型是long long intunsigned long long int,这两者通常都是64位,则intmax_tuintmax_t可以在<stdint.h>中定义为:

代码语言:javascript
复制
typedef long long int intmax_t;
typedef unsigned long long int uintmax_t;

预定义的有符号和无符号整数类型有限,范围从signedunsigned和普通charsignedunsigned long long int

C99和C11还允许实现定义扩展整数类型,这些类型不同于任何标准类型,其名称是实现定义的关键字。

在某些(但不是所有)目标上,gcc和clang都支持__int128unsigned __int128类型。它们的行为类似于128位整数类型,但它们不被视为扩展的整数类型,并且这两个编译器的文档都声明它们不支持任何扩展的整数类型。因为它们不是标准定义的整数类型,所以typedefs intmax_tuintmax_t用于64位类型,而不是128位类型。

所有这些都没有违反C标准(实现不需要有任何扩展的整数类型,只要它们不破坏任何严格符合的程序,它们就可以有任意的扩展)。但在我看来,将__int128unsigned __int128视为扩展整数类型,将intmax_tuintmax_t视为128位类型将是非常有意义的。

不这样做的理由是,更改intmax_tuintmax_t的大小将是“与ABI不兼容的更改”。

Clang C++ status page在脚注(5)中说:

对于不提供任何扩展整数类型的实现,不需要对编译器进行更改。__int128不被视为扩展整数类型,因为更改intmax_t将是与ABI不兼容的更改。

(是的,这里主要讨论C++,但规则与C相同。)

gcc bug report中,声明如下:

sizeof(intmax_t)由各种LP64 ABI修复,不能更改

在这两种情况下,都没有为这一索赔提供参考。

标题为"System V应用程序二进制接口,AMD64体系结构处理器补充,草案版本0.99.6“的x86_64 ABI document没有提到intmax_tuintmax_t,甚至没有提到<stdint.h>报头。它为预定义的整数类型指定了大小和对齐方式(如图3.1所示)。

最后,我的问题是:受ABI限制的intmax_tuintmax_t的大小是否有效?如果是这样,什么ABI强加了这样的要求?(顺便说一句,为什么?)

(在我看来,这样的要求,如果它存在的话,是不明智的。它违背了C标准允许定义扩展整数类型的目的,也违背了intmax_tuintmax_t的原意。这使得在支持128位整数类型的系统上有效使用128位整数类型变得更加困难,而在其他系统上则退回到更窄的类型。)

更新:在题为"intmax t,a way out“的N2303中,Jens Gustedt建议调整[u]intmax_t的定义,允许添加比long long更宽的扩展整数类型,而不必更新[u]intmax_t。例如,intmax_t可能是long long的一个类型定义,但是实现仍然可以提供,比如说,__int128作为扩展的整数类型。

参考文献:

由Jens Gustedt

standard

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-29 03:03:33

正如三十二上校所指出的那样,编译器单方面进行此更改将中断传递uintmax_t参数或返回uintmax_t值的编译单元之间的调用。尽管SysV ABI没有定义这些类型是如何传递的,但作为一个实用的问题,维护它们的定义是符合平台ABI的一部分。

即使不是因为这个ABI问题,编译器仍然不能单方面地进行这种更改,因为它需要对每个目标平台的C标准库进行相应的更改。具体地说,它至少需要更新printfscanf函数族、imaxabsimaxdivstrtoimaxstrtoumax及其变体。

票数 9
EN

Stack Overflow用户

发布于 2015-04-29 03:00:44

更改intmax_tuintmax_t等类型也会更改使用它们的所有程序的ABI值,因为它们现在引用不同的类型。

假设您有一个程序A,它使用共享库B中的一个带有uintmax_t参数的函数。如果GCC更改了uintmax_t的定义,并且A(而不是B)被重新编译,那么A中的uintmax_t和B中的uintmax_t现在引用了两种不同的类型,从而打破了ABI。

票数 7
EN

Stack Overflow用户

发布于 2018-06-26 00:04:36

我认为这里要理解的关键是,ABI规范中没有记录的东西并不意味着它不是ABI的一部分。一旦跨库边界使用了一个类型,它的属性就会成为该库的ABI的一部分。

通过在标准头中定义(u)intmax_t并在标准库的函数中使用它们,它们成为该库的ABI的一部分,无论它们是否包含在任何正式的ABI规范中。

对于类Unix平台来说,这尤其是一个问题,在类Unix平台中,C标准库被视为平台的一部分,而不是编译器的一部分。

现在有可能过渡到这一点。Printf使用宏作为类型说明符,因此这些宏可以根据intmax_t的大小进行不同的定义。类似地,宏可以用于将标准库中的少数函数映射到不同的实现,但这是一堆额外的工作,以获得可疑的收益,所以难怪gcc选择了阻力最小的方式来添加他们需要的功能。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29927562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档