【发布时间】:2020-07-16 14:32:07
【问题描述】:
我最近对从编写 C99 代码转换为编写普通 ANSI C (C89) 产生了兴趣,因为该语言的新特性不值得以 ANSI 编写它的极端可移植性和可靠性C. 我认为从 C99 过渡到 C89 时我会怀念的最大功能之一是 stdint.h 标准库文件;或者我是这么想的。根据this站点,C89标准中没有stdint.h文件,这也是我在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标头吗? - 如果不是,我必须采取哪些步骤来创建与
stdint.h功能相同的标头? - 在 C99 之前的时代,程序员是如何在平台无关的庄园中解决程序中整数大小可靠的问题?
【问题讨论】:
-
> “在 C99 之前的时代,程序员是如何做到的” - 一个扭曲的小 ifdef 迷宫,完全不同。 :-)
-
C89 没有义务阻止您使用系统上出现的任何标头,而不是
stdint.h或unistd.h或windows.h或任何东西别的。但是,如果您要从系统包含目录中删除stdint.h(不推荐),您的编译器仍将符合 C89,但您的代码将失败。 -
不要在 C89 中编程。一开始我也讨厌 C99,但它包含了许多需要的语言错误修复。没有隐式int。没有不可靠的整数负除法。没有“结构黑客”。 stdint.h。布尔类型。长长的。 // 厘米。编写名称超过 16 个符号的变量。等等。这是非常基本的东西,在 C89 中被彻底破坏了。
-
所有这些错误都可以说使 C89 的可移植性降低,因为有太多显而易见的错误,如果你想支持 C89,你必须避开。比如……谁不喜欢使用整数除法?
-
carsonalh,很好奇,为什么要使用
"%ld"和sizeof参数。 那个是不可移植的。printf("%lu.\n", (unsigned long) sizeof(uint8_t));更好。