Stdint.h 在 ANSI C (C89) 中

Stdint.h in ANSI C (C89)

我最近对从编写 C99 代码转向编写纯 ANSI C (C89) 感兴趣,因为该语言的新特性不值得 极端 可移植性和可靠性在 ANSI C 中编写它。我认为从 C99 过渡到 C89 时我会错过的最大功能之一是 stdint.h 标准库文件;大概我是这么想的。根据this site, there is no stdint.h file in the C89 standard, which is also what I found on Wikipedia。我想确保情况确实如此,所以我编写了一个最小的测试程序,我预计在 GCC 和 Clang 中提供标志 -ansi-pedantic-errors 时不会编译;

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    printf("The size of an int8_t is %ld.\n",  sizeof(int8_t));
    printf("The size of an int16_t is %ld.\n", sizeof(int16_t));
    printf("The size of an int32_t is %ld.\n", sizeof(int32_t));
    printf("The size of an int64_t is %ld.\n", sizeof(int64_t));

    printf("The size of a uint8_t is %ld.\n",  sizeof(uint8_t));
    printf("The size of a uint16_t is %ld.\n", sizeof(uint16_t));
    printf("The size of a uint32_t is %ld.\n", sizeof(uint32_t));
    printf("The size of a uint64_t is %ld.\n", sizeof(uint64_t));

    return 0;
}

但是,我发现的不是编译器错误,也不是警告,而是编译的程序!由于它在任何一个编译器上都工作得很好,我假设这不是编译器中的错误。作为参考,输出是人们对有效的 C99 实现的期望:

The size of an int8_t is 1.
The size of an int16_t is 2.
The size of an int32_t is 4.
The size of an int64_t is 8.
The size of a uint8_t is 1.
The size of a uint16_t is 2.
The size of a uint32_t is 4.
The size of a uint64_t is 8.

我对这个“功能”有几个问题。

Should I be able to rely upon a stdint.h header being provided for a C89 program?

没有。你说你选择 C89 是出于可移植性的原因,然后你首先要做的是不可移植的扩展......

If not, what steps would I have to take in creating a header that functions the same as stdint.h?

How did programmers, in the time before C99, solve this problem of having reliable sizes for integers in their programs in a platform-agnostic manor?

使用一大堆宏,例如 this answer。如果是 C89,您 typedef 给定平台的 stdint.h 中存在的所有名称。否则,如果是标准 C,您只需包含 stdint.h.

所以你需要你自己的“notstdint.h”,它包含所有这些,然后你必须将它移植到整数大小不同的每个系统。是的,这使得 C89 的可移植性不如标准 C。

在C89时代,写微型计算机代码时,可以简单地使用:

typedef unsigned char  uint8;
typedef signed char    int8;
typedef unsigned short uint16;
typedef signed short   int16;
typedef unsigned long  uint32;
typedef signed long    int32;

当时,int 可能是 16 位或 32 位,但所有其他类型在可以处理它们的系统(包括所有微型计算机)的常见实现中都具有指示的大小。 16 位系统的编译器将允许刚从 int* 转换为 short* 的指针访问类型 int 的对象,因此无需担心是否 int16_t 应该是 shortint。同样,32 位系统允许从 int* 新转换为 long* 的指针访问类型 int 的对象,因此不必担心是否 [=21] =] 应该是 intlong.