c - 不应该在 API 中使用枚举吗?

标签 c struct enums linker portability

我正在使用提供给我的已编译的 C 库。我对编译库时使用的编译器、版本、选项等的信息有限。库接口(interface)在传递的结构中和直接作为传递参数使用 enum

问题是:当我编译代码以使用所提供的库时,我如何确保或确定我的编译器将对这些 enum 使用相同的大小?如果没有,结构将不会排列,参数传递可能会困惑,例如longint

我的担忧源于 C99 标准,该标准规定 enum 类型:

shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration.

据我所知,只要最大值合适,编译器就可以随意选择任何类型,有效地一时兴起,可能不仅在编译器之间,而且在同一编译器的不同版本和/或编译器选项。它可以选择 1、2、4 或 8 字节表示,从而导致结构和参数传递方面的潜在不兼容。 (它也可以选择有符号或无符号,但我认为在这种情况下这不是问题的机制。)

我是不是漏掉了什么?如果我没有漏掉什么,这是否意味着 enum 永远不应在 API 中使用?

更新:

是的,我错过了一些东西。虽然语言规范在这里没有帮助,但正如@Barmar 所指出的那样,应用程序二进制接口(interface) (ABI) 可以。或者,如果没有,则 ABI 有缺陷。 ABI for my system indeed 指定 enum 必须是带符号的四字节整数。如果编译器不遵守这一点,那么它就是一个错误。给定完整的 ABI 和兼容的编译器,enum 可以在 API 中安全使用。

最佳答案

使用枚举的 API 取决于编译器将保持一致的假设,即给定相同的枚举声明,它将始终选择相同的基础类型。

虽然语言标准没有明确要求这样做,但编译器做任何其他事情都是非常不正常的。

此外,特定操作系统的所有编译器都需要与操作系统的 ABI 保持一致。否则,您会遇到更多问题,例如库使用 64 位 int 而调用方使用 32 位 int。理想情况下,ABI 应该限制 enum 的表示,以确保兼容性。

更一般地说,语言规范仅确保使用相同实现编译的程序之间的兼容性。 ABI 确保使用不同实现编译的程序之间的兼容性。

关于c - 不应该在 API 中使用枚举吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20809669/

相关文章:

c中的组合位和逻辑运算符

arrays - 在 Swift 中使用 NSCoding 归档可选结构数组?

来自其他包的 golang 结构

enums - Rust中的静态枚举

Java:我可以在枚举中使用两个不同的名称来算作同一事物吗?

c - 有效地使一个 1 全为 1 但为 0 的 int 保持为 0

c - 如何获得指向页面开头的指针

c - 在 C 语言的编译时评估的预处理器函数

go - 在 golang 中初始化包含一片结构的结构

python - 如何迭代枚举的所有值,包括任何嵌套的枚举?