使用const全局变量而不是enum是否可以确保ABI兼容性?
在我的一个C库项目中,我有一个枚举,它列出了库处理的所有可能的数据类型:使用const全局变量而不是enum是否可以确保ABI兼容性?,c,abi,C,Abi,在我的一个C库项目中,我有一个枚举,它列出了库处理的所有可能的数据类型: // lib.h enum types { VOID, INT, FLOAT, CONST_INT, CONST_FLOAT } 代码将被编译到一个共享库中。在库的未来版本中,我将被要求在枚举中插入新条目并对现有条目重新排序。AFAIK这会破坏ABI兼容性,因为枚举不会转换为一组符号,这些符号最终会出现在库中,而是会导致编译器分配给每个条目的任何整数都被硬编码。是这样吗 如果是这样
// lib.h
enum types {
VOID,
INT,
FLOAT,
CONST_INT,
CONST_FLOAT
}
代码将被编译到一个共享库中。在库的未来版本中,我将被要求在枚举中插入新条目并对现有条目重新排序。AFAIK这会破坏ABI兼容性,因为枚举不会转换为一组符号,这些符号最终会出现在库中,而是会导致编译器分配给每个条目的任何整数都被硬编码。是这样吗
如果是这样,是否最好改用常量全局变量,使其出现在符号表中,从而可以更改顺序和分配给每个变量的值
// 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;
你说得对。如果计划展开枚举变量,则可能会使库的未来版本不兼容。 如果您查看一些最相关的软件,例如MS或linux头文件,您会发现采用的解决方案主要有两种: 使用定义 仍然使用enum,但为每个条目分配一个值 后者使enum的使用与defines相当,但保留了enum的属性。 在您的情况下,可能是:
// 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
}
常量全局变量的使用可能会有一些问题,甚至需要进行优化并用常量替换。最好的方法是将枚举放在该库的头文件中 更改枚举仍将需要重新编译/链接库等 为确保枚举中的每个标签都具有特定值,枚举的写入方式类似于:
enum
{
label1 = 0,
label2 = 1,
label3 = 20,
label4 = 5
};
结果将显示在匿名枚举中,其中每个标签都是可见的并具有相应的值。请注意,向枚举添加条目会更改类型,并可能会生成用于存储枚举变量的更大整数类型,这就是为什么您偶尔会看到大的/负的保留填充条目以备将来验证。诚然,在实践中,这主要是8位ABI上的一个问题,尤其是对于连续枚举。@doynax解决方案是使用int作为任何变量的类型,该变量将包含这些枚举数中的一个。所有枚举数都是int,而不考虑enum@M.M:这确实是最常见的解决方法。但是,在破译这些值时,调试器没有提供任何帮助,这有点烦人。