将成员添加到C样式结构和向后兼容性

时间:2010-07-22 13:57:21

标签: c api struct backwards-compatibility

假设我有一个在低级代码深处某处定义的结构,以最疯狂和未知的方式在整个地方使用:

struct T {
    unsigned short name_len;
    char d_name[LENGTH];
}

附带的函数可以填充d_name以及需要放在那里的任何内容,例如

struct T* fill( somethingOrOther* X)

我想扩展旧的struct +函数以包含一个新变量:

struct T {
    unsigned short name_len;
    char d_name[LENGTH];
    unsigned short type_len;
    char d_type;
}

并且该函数的新版本也将用有用的东西填充d_type变量。

此类更改是否会破坏API?我不能只使用新的T而不是旧的T,并另外访问新的成员吗?

5 个答案:

答案 0 :(得分:4)

扩展你的结构可能是有道理的:

struct newT {
    struct T t;
    int newElement;
    ...
}

然后你可以安全地使用newT指针作为T指针; C标准保证在结构的第一个元素之前没有填充。

答案 1 :(得分:3)

只要使用此API的代码仅获取T个对象作为库返回的指针,并且不自己声明它们,malloc它们本身(使用sizeof(struct T)),或者做任何其他取决于结构的大小,那么它应该没问题。如果调用代码访问了结构的内容,则需要确保将新成员放在结构的末尾。

一个可能的额外考虑因素是,如果声明的大小不合适,任何代码是否依赖于d_name位于结构的末尾,以便为更大的名称分配空间和存储更大的名称。我只提出这个问题,因为成员的名字表明结构类似于dirent,这是dirent的传统做法。

答案 2 :(得分:2)

如果T真的以疯狂和未知的方式在整个地方使用,那么这样的改变很可能会破坏某些东西。在某处会有一段代码具有T的本地声明而不是使用您的头文件,或者将'mystruct *'转换为'T *',或者同样令人反感的东西。

答案 3 :(得分:1)

是的 - 当你使用像这样的不透明指针时,它与内容无关。只要你的用户只使用过不透明的指针,你就可以随意使用结构,并且你可以随心所欲地实现它。

答案 4 :(得分:0)

疯狂和未知不好。最好的办法是扫描struct T的代码库并检查它是如何使用的,使用替代方法更改它并查看是否有问题...如果代码只使用不透明指针,那么您应该安全。如果代码访问成员,但没有做一些奇怪的事情,那么你也应该是安全的,完全重新编译。

如果它做了一些奇怪的事情,比如rettops的例子,即使是Jukka的提示也可能无济于事。代码可以使用sizeof的硬编码值在这些结构的数组中进行指针运算......