在 C89 中是否有任何 well-established/standardized 方法来使用 fixed-width 整数?

Are there any well-established/standardized ways to use fixed-width integers in C89?

一些背景:

headerstdint.h is part of the C standard since C99。它包括确保为 8、16、32 和 64 位长整数(有符号和无符号)的 typedef。不过,这个 header 不是 C89 标准的一部分,而且我还没有找到任何 直接 方法来确保我的数据类型具有已知长度。

进入正题

下面的代码是SQLite(用C89写的)如何定义64位整数,但我觉得没有说服力。也就是说,我认为它不会在任何地方都有效。最糟糕的是,它可能会无声地失败:

/*
** CAPI3REF: 64-Bit Integer Types
** KEYWORDS: sqlite_int64 sqlite_uint64
**
** Because there is no cross-platform way to specify 64-bit integer types
** SQLite includes typedefs for 64-bit signed and unsigned integers.
*/
#ifdef SQLITE_INT64_TYPE
  typedef SQLITE_INT64_TYPE sqlite_int64;
  typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
#elif defined(_MSC_VER) || defined(__BORLANDC__)
  typedef __int64 sqlite_int64;
  typedef unsigned __int64 sqlite_uint64;
#else
  typedef long long int sqlite_int64;
  typedef unsigned long long int sqlite_uint64;
#endif
typedef sqlite_int64 sqlite3_int64;
typedef sqlite_uint64 sqlite3_uint64;

所以,这就是我到目前为止一直在做的事情:

我已经在一个 header 文件中抽象了这个过程,这是我所能做的最好的,但我想知道是否有更直接的方法来实现这个。

我问是因为我想写一个可移植的 C 库。

首先,您应该问问自己是否真的需要支持不提供 <stdint.h> 的实现。它在 1999 年被标准化,甚至许多 C99 之前的实现也可能将其作为扩展提供。

假设您真的需要这个,ISO C 标准委员会的成员 Doug Gwyn 为 C9x(当时称为 C99)创建了几个新 headers 的实现,与 C89/C90。 headers 位于 public 域中,应该具有合理的可移植性。

http://www.lysator.liu.se/(nobg)/c/q8/index.html

(据我了解,"q8" 这个名字没有特别的含义;他只是选择它作为一个相当简短且独特的搜索词。)

C 中整数类型的一个相当讨厌的怪癖源于这样一个事实,即许多 "modern" 实现对于至少一种整数大小,具有相同大小的两个不兼容的带符号类型,具有相同的位表示和同样是两个不兼容的无符号类型。最典型的类型是 32 位 "int" 和 "long",或 64 位 "long" 和 "long long"。 "fixed-sized" 类型通常会成为其中一种标准类型的别名,但具体实现方式并不一致。

虽然编译器过去假设访问一种给定大小的类型可能会影响另一种类型的对象,但标准的作者并没有强制要求他们这样做(可能是因为没有必要命令人们做他们无论如何都会做的事情,他们无法想象任何理智的编译器作者会做其他事情;一旦编译器开始这样做,在政治上就很难撤销 "permission")。因此,如果一个库以 32 位 "int" 存储数据,而另一个库从 32 位 "long" 读取数据,则确保正确行为的唯一方法是禁用别名完全分析(可能是使用 gcc 时最明智的选择)或者添加无偿复制操作(注意 gcc 不会优化它们,然后使用它们的缺失作为破坏代码的借口——从 6.2 开始它有时会这样做)。