假设我有一个在低级代码深处某处定义的结构,以最疯狂和未知的方式在整个地方使用:
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,并另外访问新的成员吗?
答案 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的硬编码值在这些结构的数组中进行指针运算......