在标准 C 中声明固定大小整数 typedef

发布于 2024-08-07 02:21:19 字数 325 浏览 4 评论 0原文

ISO 标准 C 中是否有可靠的方法来声明固定 8、16、32 和 64 位长度的整数类型的 typedef?

当我说 ISO 标准 C 时,我的意思是严格意义上的:

  • ISO C89/C90,而不是 C99。
  • ISO 标准中没有定义任何标题。
  • ISO 标准中没有定义任何预处理器符号。
  • ISO 标准中未指定任何类型大小假设。
  • 没有专有的供应商符号。

我在 StackOverflow 中看到了与此类似的其他问题,但还没有不违反上述约束之一的答案。我不确定如果不诉诸平台符号是否可能。

Is there a reliable way to declare typedefs for integer types of fixed 8,16,32, and 64 bit length in ISO Standard C?

When I say ISO Standard C, I mean that strictly:

  • ISO C89/C90, not C99.
  • No headers not defined in the ISO standard.
  • No preprocessor symbols not defined in the ISO standard.
  • No type-size assumptions not specified in the ISO standard.
  • No proprietary vendor symbols.

I see other questions similar to this in StackOverflow, but no answers yet that do not violate one of the above constraints. I'm not sure it's possible without resorting to platform symbols.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甜尕妞 2024-08-14 02:21:19

是的你可以。

头文件 limits.h 应该是 C90 的一部分。然后,我将测试 SHRT_MAXINT_MAXLONG_MAXLLONG_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

Yes you can.

The header file limits.h should be part of C90. Then I would test through preprocessor directives values of SHRT_MAX, INT_MAX, LONG_MAX, and LLONG_MAX and set typedefs accordingly.

Example:

#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
つ可否回来 2024-08-14 02:21:19

严格来说,ISO 9899:1999 取代了 ISO 9899:1990,因此是当前唯一的 ISO 标准 C 语言规范。

由于整数类型的精确宽度 typedef 名称仅在 1999 版本的标准中引入,因此仅使用 1990 版本的标准是不可能实现您想要的。

Strictly speaking, ISO 9899:1999 superceded ISO 9899:1990 so is the only current ISO standard C language specification.

As exact width typedef names for integer types were only introduced into the standard in the 1999 version, what you want is not possible using only the 1990 version of the standard.

海之角 2024-08-14 02:21:19

没有。但是,如果您愿意接受一些限制,则有一种可靠的方法可以声明大小最大为 32 位的单个整数变量。只需使用 long 位域(后者保证至少为 32 位宽,并且如果位域声明符是,则允许在位域中使用与变量适合的位数一样多的位)省略)。所以:

struct {
   unsigned long foo : 32; 
} bar;

显然,你会受到随之而来的所有限制,例如无法拥有指向此类变量的指针。这真正为您带来的唯一好处是保证在上溢/下溢时在指定边界处环绕,即使这样也仅适用于无符号类型,因为溢出对于有符号是未定义的。

除此之外,没有可移植的方法可以在纯 C90 中执行此操作。除此之外,例如,一致的 C90 实现甚至不需要有 8 位整数 - 拥有一个其中 sizeof(char) == sizeof(short) == sizeof(int) 的平台是完全合法的) == 1CHAR_BIT == 16 (即它有一个 16 位机器字,并且不能寻址单个字节)。我听说这样的平台实际上以一些 DSP 的形式存在于实践中。

There is none. There is a reliable way to declare individual integer variables up to 32 bits in size, however, if you're willing to live with some restrictions. Just use long bitfields (the latter is guaranteed to be at least 32-bit wide, and you're allowed to use up to as many bits in a bitfields as would fit in the variable if bitfield declarator was omitted). So:

struct {
   unsigned long foo : 32; 
} bar;

Obviously, you get all the limitations that come with that, such as inability to have pointers to such variables. The only thing this really buys you is guaranteed wraparound at the specified boundary on over/underflow, and even then only for unsigned types, since overflow is undefined for signed.

Aside from that, there's no portable way to do this in pure C90. Among other things, a conformant C90 implementation need not even have a 8-bit integer, for example - it would be entirely legal to have a platform in which sizeof(char) == sizeof(short) == sizeof(int) == 1 and CHAR_BIT == 16 (i.e. it has a 16-bit machine word, and cannot address individual bytes). I've heard that such platforms do in fact exist in practice in form of some DSPs.

陈独秀 2024-08-14 02:21:19

使用现代编译器时,这种方法的一个危险是,编译器假设一种整数类型的指针不会用于访问另一种整数类型的值已经变得很流行,即使两种类型具有相同的大小和表示形式 /em>。如果两种类型具有相同的大小和表示形式,并且同一程序的两个部分各自选择其中之一,则对共享指向此类数据的指针的程序应用链接时优化可能会导致不正确的行为。对于许多系统上的某些实现,至少有一种大小的整数,不可能为其声明一个可以安全地用于访问该大小的所有整数值的指针;例如,在 longlong long 都是 64 位的系统上,将无法声明一个可以可靠地用于互换地访问任一类型数据的指针。

A danger with such approaches when using modern compilers is that it has become fashionable for compilers to assume that a pointer of one integer type will not be used to access values of another, even when both types have the same size and representation. If two types have the same size and representation, and two parts of the same program each choose one of them, applying link-time optimizations to programs that share pointers to such data could result in improper behavior. For some implementations on many systems, there will be at least one size of integer for which it will be impossible to declare a pointer which can be safely used to access all integer values of that size; e.g. on systems where both long and 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.

看轻我的陪伴 2024-08-14 02:21:19

不,你不能那样做。

现在,如果您想将像 Gnu configure 这样的多阶段配置过程视为解决方案,您可以这样做并坚持使用 C89。当然,您可以在 C89 中使用多种类型,并且这将在当今几乎所有实现上进行 DTRT,因此您可以获得所需的大小并坚持使用纯一致的 C89。但是,虽然您想要什么位宽,但标准通常不会指定位宽。

No, you can't do that.

Now, if you want to count a multi-stage configuration process like Gnu configure as a solution, you can do that and stick to C89. And there are certainly various types you can use that are in C89, and that will DTRT on almost every implementation that's around today, so you get the sizes you want and stick with pure conforming C89. But the bit widths, while what you want, will not in general be specified by the standard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文