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.
我对这个“功能”有几个问题。
- 我是否可以依赖为 C89 程序提供的
stdint.h
header?
- 如果不是,我必须采取什么步骤来创建一个功能与
stdint.h
相同的 header?
- 在 C99 之前的时间里,程序员是如何在 platform-agnostic 庄园中解决程序中整数的可靠大小的问题?
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
应该是 short
或 int
。同样,32 位系统允许从 int*
新转换为 long*
的指针访问类型 int
的对象,因此不必担心是否 [=21] =] 应该是 int
或 long
.
我最近对从编写 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.
我对这个“功能”有几个问题。
- 我是否可以依赖为 C89 程序提供的
stdint.h
header? - 如果不是,我必须采取什么步骤来创建一个功能与
stdint.h
相同的 header? - 在 C99 之前的时间里,程序员是如何在 platform-agnostic 庄园中解决程序中整数的可靠大小的问题?
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
应该是 short
或 int
。同样,32 位系统允许从 int*
新转换为 long*
的指针访问类型 int
的对象,因此不必担心是否 [=21] =] 应该是 int
或 long
.