从1999年版本开始,ISO标准定义了一个标准头<stdint.h>
,其中定义了typedefs intmax_t
和uintmax_t
。它们分别指定“能够表示任何(有符号|无符号)整数类型的任何值的(有符号|无符号)整数类型”。
例如,通常情况下,如果最宽的带符号和无符号整数类型是long long int
和unsigned long long int
,这两者通常都是64位,则intmax_t
和uintmax_t
可以在<stdint.h>
中定义为:
typedef long long int intmax_t;
typedef unsigned long long int uintmax_t;
预定义的有符号和无符号整数类型有限,范围从signed
、unsigned
和普通char
到signed
和unsigned
long long int
。
C99和C11还允许实现定义扩展整数类型,这些类型不同于任何标准类型,其名称是实现定义的关键字。
在某些(但不是所有)目标上,gcc和clang都支持__int128
和unsigned __int128
类型。它们的行为类似于128位整数类型,但它们不被视为扩展的整数类型,并且这两个编译器的文档都声明它们不支持任何扩展的整数类型。因为它们不是标准定义的整数类型,所以typedefs intmax_t
和uintmax_t
用于64位类型,而不是128位类型。
所有这些都没有违反C标准(实现不需要有任何扩展的整数类型,只要它们不破坏任何严格符合的程序,它们就可以有任意的扩展)。但在我看来,将__int128
和unsigned __int128
视为扩展整数类型,将intmax_t
和uintmax_t
视为128位类型将是非常有意义的。
不这样做的理由是,更改intmax_t
和uintmax_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_t
或uintmax_t
,甚至没有提到<stdint.h>
报头。它为预定义的整数类型指定了大小和对齐方式(如图3.1所示)。
最后,我的问题是:受ABI限制的intmax_t
和uintmax_t
的大小是否有效?如果是这样,什么ABI强加了这样的要求?(顺便说一句,为什么?)
(在我看来,这样的要求,如果它存在的话,是不明智的。它违背了C标准允许定义扩展整数类型的目的,也违背了intmax_t
和uintmax_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
发布于 2015-04-29 03:03:33
正如三十二上校所指出的那样,编译器单方面进行此更改将中断传递uintmax_t
参数或返回uintmax_t
值的编译单元之间的调用。尽管SysV ABI没有定义这些类型是如何传递的,但作为一个实用的问题,维护它们的定义是符合平台ABI的一部分。
即使不是因为这个ABI问题,编译器仍然不能单方面地进行这种更改,因为它需要对每个目标平台的C标准库进行相应的更改。具体地说,它至少需要更新printf
和scanf
函数族、imaxabs
、imaxdiv
、strtoimax
和strtoumax
及其变体。
发布于 2015-04-29 03:00:44
更改intmax_t
和uintmax_t
等类型也会更改使用它们的所有程序的ABI值,因为它们现在引用不同的类型。
假设您有一个程序A,它使用共享库B中的一个带有uintmax_t
参数的函数。如果GCC更改了uintmax_t
的定义,并且A(而不是B)被重新编译,那么A中的uintmax_t
和B中的uintmax_t
现在引用了两种不同的类型,从而打破了ABI。
发布于 2018-06-26 00:04:36
我认为这里要理解的关键是,ABI规范中没有记录的东西并不意味着它不是ABI的一部分。一旦跨库边界使用了一个类型,它的属性就会成为该库的ABI的一部分。
通过在标准头中定义(u)intmax_t并在标准库的函数中使用它们,它们成为该库的ABI的一部分,无论它们是否包含在任何正式的ABI规范中。
对于类Unix平台来说,这尤其是一个问题,在类Unix平台中,C标准库被视为平台的一部分,而不是编译器的一部分。
现在有可能过渡到这一点。Printf使用宏作为类型说明符,因此这些宏可以根据intmax_t的大小进行不同的定义。类似地,宏可以用于将标准库中的少数函数映射到不同的实现,但这是一堆额外的工作,以获得可疑的收益,所以难怪gcc选择了阻力最小的方式来添加他们需要的功能。
https://stackoverflow.com/questions/29927562
复制相似问题