使用 const global vars 而不是 enum 是否确保 ABI 兼容性?

Does using const global vars instead of enum ensure ABI compatibility?

在我的一个 C 库项目中,我有一个枚举,它列出了所有可能的类型,库处理的一段数据可以是:

// lib.h
enum types {
    VOID,
    INT,
    FLOAT,
    CONST_INT,
    CONST_FLOAT
}

代码将被编译到共享库中。在该库的未来版本中,我将需要向枚举中插入新条目并对现有条目重新排序。 AFAIK 这破坏了 ABI 兼容性,因为枚举没有转换为一组最终出现在库中的符号,而是导致编译器分配给每个条目的任何整数被硬编码。是这样吗?

如果是这样,是否最好改用常量全局变量,使它们出现在符号 table 中,这样我就可以更改顺序和分配给每个变量的值?

// lib.c
const int VOID = 1;
const int INT = 2;
const int FLOAT = 3;
const int CONST_INT = 4;
const int CONST_FLOAT = 5;

// lib.h
extern const int VOID;
extern const int INT;
extern const int FLOAT;
extern const int CONST_INT;
extern const int CONST_FLOAT;

你是对的。如果您计划扩展枚举变量,它可能会使您的库的未来版本不兼容。
如果你看看一些最相关的 sw around(即 MS 或 linux headers),你可以看到采用的解决方案主要有两个:

  1. 使用定义
  2. 仍然使用枚举,但为每个条目分配一个值

后者使枚举的使用完全等同于定义,但保留了枚举的属性。
在您的情况下,它可能是:

// lib.h
enum types {
    VOID = 0,
    INT = 1,
    FLOAT = 10,
    CONST_INT = 12,
    CONST_FLOAT = 13
}

那么以后你会添加其他代码:

// lib.h
enum types {
    VOID = 0,
    INT = 1,
    CUSTOM1 = 3,
    FLOAT = 10,
    CUSTOM2 = 11,
    CONST_INT = 12,
    CONST_FLOAT = 13,
    CUSTOM4 = 20
}

常量全局变量的使用可能会有一些问题,甚至被优化掉并被常量替换。

最好的方法是将枚举放在该库的头文件中。

更改枚举仍然需要库的 re-compiling/linking 等(无法回避),

为了确保枚举中的每个标签都有特定的值,枚举可以写成类似于:

enum 
{
    label1 = 0,
    label2 = 1,
    label3 = 20,
    label4 = 5
};

匿名枚举中的结果,其中每个标签都是可见的并具有适当的值。