使用 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),你可以看到采用的解决方案主要有两个:
- 使用定义
- 仍然使用枚举,但为每个条目分配一个值
后者使枚举的使用完全等同于定义,但保留了枚举的属性。
在您的情况下,它可能是:
// 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
};
匿名枚举中的结果,其中每个标签都是可见的并具有适当的值。
在我的一个 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),你可以看到采用的解决方案主要有两个:
- 使用定义
- 仍然使用枚举,但为每个条目分配一个值
后者使枚举的使用完全等同于定义,但保留了枚举的属性。
在您的情况下,它可能是:
// 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
};
匿名枚举中的结果,其中每个标签都是可见的并具有适当的值。