在 ISO 标准 C 中,是否有一种可靠的方法来为固定 8、16、32 和 64 位长度的整数类型声明 typedef?
当我说 ISO 标准 C 时,我的意思是严格地说:
- ISO C89/C90,不是 C99。
- 没有未在 ISO 标准中定义的标头。
- 没有未在 ISO 标准中定义的预处理器符号。
- 没有 ISO 标准中未指定的字体大小假设。
- 没有专有的供应商符号。
我在 StackOverflow 中看到了与此类似的其他问题,但还没有不违反上述限制之一的答案。我不确定不诉诸平台符号是否可行。
在 ISO 标准 C 中,是否有一种可靠的方法来为固定 8、16、32 和 64 位长度的整数类型声明 typedef?
当我说 ISO 标准 C 时,我的意思是严格地说:
我在 StackOverflow 中看到了与此类似的其他问题,但还没有不违反上述限制之一的答案。我不确定不诉诸平台符号是否可行。
是的,你可以。
头文件limits.h
应该是 C90 的一部分。然后,我将通过预处理器指令的SHRT_MAX
、INT_MAX
、LONG_MAX
和的值进行测试,LLONG_MAX
并相应地设置 typedef。
例子:
#include <limits.h>
#if SHRT_MAX == 2147483647
typedef unsigned short int uint32_t;
#elif INT_MAX == 2147483647
typedef unsigned int uint32_t;
#elif LONG_MAX == 2147483647
typedef unsigned long uint32_t ;
#elif LLONG_MAX == 2147483647
typedef unsigned long long uint32_t;
#else
#error "Cannot find 32bit integer."
#endif
严格来说,ISO 9899:1999 取代了 ISO 9899:1990,因此是目前唯一的 ISO 标准 C 语言规范。
由于整数类型的精确宽度 typedef 名称仅在 1999 版本的标准中引入,因此仅使用 1990 版本的标准无法实现您想要的。
空无一人。但是,如果您愿意接受一些限制,则有一种可靠的方法可以声明最大为 32 位的单个整数变量。只需使用long
位域(后者保证至少为 32 位宽,并且如果省略位域声明符,您可以在位域中使用尽可能多的位,以适应变量)。所以:
struct {
unsigned long foo : 32;
} bar;
显然,您会得到所有随之而来的限制,例如无法拥有指向此类变量的指针。唯一真正为您买的东西是保证在上溢/下溢的指定边界处环绕,即使这样也仅适用于无符号类型,因为溢出对于有符号是未定义的。
除此之外,在纯 C90 中没有可移植的方式来执行此操作。除此之外,一个符合 C90 的实现甚至不需要一个 8 位整数,例如 - 拥有一个平台是完全合法的sizeof(char) == sizeof(short) == sizeof(int) == 1
(CHAR_BIT == 16
即它有一个 16 位机器字,并且不能寻址单个字节) . 我听说这样的平台实际上以某些 DSP 的形式存在于实践中。
使用现代编译器时,这种方法的一个危险是,编译器已经流行假设一种整数类型的指针不会用于访问另一种类型的值,即使两种类型具有相同的大小和表示。如果两种类型具有相同的大小和表示,并且同一程序的两个部分各自选择其中之一,则将链接时优化应用于共享指向此类数据的指针的程序可能会导致不正确的行为。对于许多系统上的某些实现,将存在至少一种整数大小,不可能为其声明一个可以安全地用于访问该大小的所有整数值的指针;例如在系统上同时long
和long long
are 64 bits, there will be no way to declare a pointer which can be used reliably to access data of either type interchangeably.
不,你不能那样做。
现在,如果你想把像 Gnu 这样的多阶段配置过程算作configure
一个解决方案,你可以这样做并坚持使用 C89。当然,您可以在 C89 中使用各种类型,这将在当今几乎所有的实现中进行 DTRT,因此您可以获得所需的大小并坚持使用纯符合 C89。但是位宽,虽然你想要什么,但通常不会由标准指定。