【问题标题】:Why does everybody typedef over standard C types?为什么每个人都对标准 C 类型进行 typedef?
【发布时间】:2016-07-24 12:59:38
【问题描述】:

如果你想使用Qt,你必须拥抱quint8quint16等等。

如果你想使用GLib,你必须欢迎guint8guint16等等。

Linux 上有u32s16 等等。

uC/OS 定义SINT32UINT16 等等。

如果你必须使用这些东西的某种组合,你最好为麻烦做好准备。因为在您的机器上,u32 将是 typedefd 而不是 longquint32 将是 typedefd 而不是 int 并且编译器会抱怨

如果有<stdint.h>,为什么每个人都这样做?这是图书馆的某种传统吗?

【问题讨论】:

  • @Mehrdad 在微控制器编程中你可以拥有各种各样的东西。例如,在 AVR Mega 上(因此在著名的 Arduino 上)int 是 16 位的。这可能是一个令人讨厌的惊喜。在我看来,“无符号短”需要更多的打字工作。对于 byte 八位字节使用 'unsigned char' 总是让我感到难过。无符号字符,真的吗?
  • @Mehrdad 关键是你不能确定。这正是stdint.h 被发明的原因。
  • @glglgl:这是看待问题的另一种方式:你不是问错了问题吗?如果您的目标是多个系统,为什么一开始就任意将位数硬编码到代码中?即,为什么不直接说sizeof(int) * CHAR_BIT(例如)并使用它?如果您的int 太小而无法代表您的范围(例如数组索引),那么您几乎肯定不应该使用int,而是使用size_t 之类的东西。为什么int32 更有意义?唯一有意义的固定宽度是用于系统之间的通信(例如文件/网络格式)......
  • @Mehrdad 不。有时我有需要存储的值(例如来自 ADC 或其他)。我知道它们是 16 位宽的。所以最好使用uint16_t(或者它的fastleast 变体)。我的观点是:这些类型使用方便,有其存在的理由。
  • @Mehrdad:我建议——假设你努力生成高质量的代码——你应该定义自己的函数类型定义,这意味着 与我的 API 交互的方式/我的其余部分代码,并根据“技术”类型定义(如size_t 和/或uint64_t)在技术基础上定义这些。

标签: c++ c stdint


【解决方案1】:

stdint.h 在开发这些库时并不存在。所以每个图书馆都有自己的typedefs。

【讨论】:

  • 好吧,我认为缺少 stdint.h 是一个很好的理由,但为什么即使在今天这些 typedef 都超过 int、long 等而不是超过 stdint 类型?这将使它们至少可以互换
  • @Amomum “为什么 Glib(在 Linux 上开发的)不使用 Linux 类型定义?”虽然 glib 的“大本营”当然是 Linux,但它在设计上肯定是一个可移植的库。定义自己的类型可确保可移植性:只需调整一个与库类型匹配的微小标头即可适应相应的目标平台类型。
  • @Amomum 为什么是 Glib(在 Linux 上开发的)... 不,不是。 Glib 是在 Linux 内核之前方式创建的。
  • @andy256 "GLib" 不是 "glibc" 的缩写。这是一个从 gtk 分支出来的库。它不比 Linux 更早。
  • @andy256:glib 是 1998 年,linux 是 1991 年。IOW,GLib 是在 Linux 之后创建的。
【解决方案2】:

对于较旧的库,这是必需的,因为相关标头 (stdint.h) 不存在。

但是,仍然存在一个问题:这些类型(uint64_t 和其他类型)在标准中是可选功能。因此,合规的实现可能不会随它们一起提供——因此现在迫使库仍然包含它们。

【讨论】:

  • uintN_t 类型是可选的,但 uint_leastN_tuint_fastN_t 类型不是。
  • @Kusalananda:可悲的是,它们的用处有限。
  • 当然,它们是可选的原因是您不能保证有 个整数类型具有完全相同的位数。 C 仍然支持具有相当奇数整数大小的架构。
  • @LightnessRacesinOrbit:它们的用处如何?我必须承认,除了硬件接口之外,我不明白为什么您需要准确的位数,而不仅仅是最小值,以确保您的所有值都适合。
  • @Amomum The typedefs are 如果实现具有满足要求的类型:“但是,如果实现提供宽度为 8、16、32 或 64 的整数类型位,没有填充位,并且(对于有符号类型)具有二进制补码表示,它应定义相应的 typedef 名称。” (引自 N1570, 7.20.1.1 "Exact-width integer types")因此,如果标准库没有它们,第三方库似乎也不能。
【解决方案3】:

stdint.h 自 1999 年以来已被标准化。很可能许多应用程序定义(实际上是别名)类型以保持与底层机器架构的部分独立性。

它们让开发人员确信在他们的应用程序中使用的类型符合他们项目特定的行为假设,而这些假设可能与语言标准或编译器实现都不匹配。

这种做法反映在面向对象的 Façade 设计模式中,并且被开发人员滥用,他们总是为所有导入的库编写包装类。

当编译器不那么标准并且机器架构可能从 16 位 18-bit36-bit 字长大型机变化时,这是一个更多的考虑因素。现在,在融合 32 位 ARM 嵌入式系统的世界中,这种做法的相关性要小得多。对于具有odd 内存映射的低端微控制器来说,这仍然是一个问题。

【讨论】:

  • 诚然,stdint.h 自 1999 年以来已被标准化,但它在实践中可用多久了?人们在实施和采用新标准时拖拖拉拉,在漫长的过渡期内,旧方法仍然是必须的。
  • stdint.h 的一个令人讨厌的问题是,即使在平台上,例如longint32_t 具有相同的大小和表示形式,没有要求将 int32_t* 转换为 long* 会产生一个可以可靠地访问 int32_t 的指针。我不敢相信标准的作者认为布局兼容的类型显然应该是别名兼容的,但是由于他们没有费心这么说,gcc 和 IIRC clang 的作者认为即使忽略别名也会改进语言在明显的情况下。
  • @supercat -- 这可能值得作为勘误表提交给 C 委员会...因为这是无端愚蠢,委婉地说
  • @LThode:C 委员会要承认这是一个错误,需要正式宣布 clang 和 gcc 的行为是迟钝的。你认为这会发生吗?最好的希望(恕我直言,这是合乎逻辑的进行方式)是为程序定义指定“别名模式”的方法。如果一个程序指定它可以接受非常严格的别名规则,那么编译器可以使用它来允许超出目前可能的优化。如果一个程序指定它需要比现有规则更适合程序员的规则......
  • ...但是仍然允许许多有用的优化,然后编译器可以生成比-fno-strict-alias 更有效的代码,但实际上仍然可以工作。即使没有现有的代码库,也没有单一的规则集可以为所有应用程序实现优化和语义的最佳平衡,因为不同的应用程序有不同的需求。添加现有代码库,不同模式的需求应该很清楚。
【解决方案4】:

所以你有能力将 char 类型转换为 int。

一个“编码恐惧”提到,一个公司的标题有一个程序员想要一个布尔值的地方,而 char 是该工作的逻辑本机类型,所以写了typedef bool char。后来有人发现整数是最合乎逻辑的选择,并写了typedef bool int。结果,早于 Unicode,实际上是 typedef char int

我认为有很多前瞻性和向前兼容性。

【讨论】:

    猜你喜欢
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多