【问题标题】:How do you deal with the native size of integers changing between platforms?您如何处理平台之间变化的整数的本机大小?
【发布时间】:2011-08-31 05:30:30
【问题描述】:

恐怕我已经知道这个问题的答案,但我想确定......

我有一个相当大的项目,其中包含一个对原生类型进行 typedef 的头文件:

typedef unsigned long int    u32;
typedef signed long int      s32;
// etc...

不可避免的事情已经发生,我现在尝试在long 是 64 位而不是 32 位的系统上进行编译。修复它的最佳方法是什么?

我可以用int(或来自stdint.h的int32_t/uint32_t)在上面typedef,这将满足我所知道的平台上的32位大小,但这似乎仍然值得怀疑。使用%ldprintf 样式函数也存在问题(编译器抱怨并希望看到%d)。这些都必须改变,不是吗(也许在 inttypes.h 中有定义)?

这看起来很简单,但在我开始深入研究之前我想确定一下(修复printf 格式字符串似乎令人生畏)。

【问题讨论】:

  • 什么时候真正重要?为什么不能只使用unsigned int?这是便携式的,只是大小无法预测。
  • 当您将非long 传递给%ld 时,您的编译器应该给出警告,并且使用标志您应该能够将该警告变为错误。这让您有机会解决所有问题。
  • @Dietrich:这对于大多数简单情况来说都很好,在这些情况下,您的格式字符串是对printf 的调用中的文字。当格式字符串来自其他地方(例如一组本地化字符串)时,编译器无济于事。这就是为什么在此类本地化字符串中仅使用%s 并在涉及特定于语言的代码之前将数字转换为字符串或使用比可变参数更安全的东西是一个好主意的原因之一。但是,如果您已经以另一种方式完成了它,那么改变它是一项工作。所以你说的值得去做,但并不能解决所有问题。
  • @Steve Jessop:公平,但您通常可以定义一个宏来将本地化字符串作为文字传递,其余情况相对较少。

标签: c++ c portability


【解决方案1】:

C 有 <stdint.h>,在 C++0x 中是 <cstdint>。对于非 C++0x 编译器,如果您不介意依赖 Boost,则可以使用 <boost/cstdint.hpp><inttypes.h> 标头还包括printf() 格式说明符的宏,它可以是adapted for use<cstdint> 类型。如果您使用 C++,则应该使用 <iostream>,因此无需担心类型化格式说明符。

【讨论】:

  • @Jon:你总是可以从 Boost 中撕下标头(保留许可证...),我想它是相当独立的...
【解决方案2】:

创建与您的库/可执行文件一起编译的单个翻译 (.cpp)。在其中,使用静态断言。如果您需要特定的大小,这种方法可以在您创建可链接/可执行二进制文件之前确认您的声明是否符合您需要它们匹配的条件,以防环境发生变化。

然后打开编译器警告并修复必须修复的问题。

【讨论】:

    【解决方案3】:

    关于可移植 32 位整数(等)的解决方案:

    • 在一些手工构建的配置文件中定义您自己的可移植类型或
    • 使用stdint.h 为您完成此操作,并保证在任何与 C99 兼容的 C 编译器中都存在。

    printf 而言,stdint.hprintf 提供了可移植的宏。或者只使用 C++ I/O,然后您就不必担心printf 格式。

    【讨论】:

    • <stdint.h> 标头不包含printf 宏,可以在<inttypes.h> 中找到。
    猜你喜欢
    • 1970-01-01
    • 2020-12-20
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-25
    • 2021-04-16
    • 2018-06-13
    相关资源
    最近更新 更多