代码之家  ›  专栏  ›  技术社区  ›  rubenvb

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

  •  7
  • rubenvb  · 技术社区  · 14 年前

    假设我有一个在底层代码深处定义的结构,它以最疯狂和未知的方式在各处使用:

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

    附带的函数用需要放在那里的任何东西填充d_名称,比如

    struct T* fill( somethingOrOther* X)
    

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

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

    新版本的函数也会用有用的东西填充d_类型的变量。

    这种类型的更改会破坏API吗?我不能用新的T代替旧的T,另外访问新的成员吗?

    5 回复  |  直到 9 年前
        1
  •  3
  •   R.. GitHub STOP HELPING ICE    14 年前

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

    另一个可能的考虑因素是是否有任何代码依赖于 d_name 位于结构的末尾,以便在声明的大小不合适时为较大的名称分配空间并存储较大的名称。我之所以提起这个,是因为成员的名字表明结构类似于 dirent 这是传统的做法 目录项 .

        2
  •  4
  •   Jukka Suomela    14 年前

    像这样扩展结构可能是有意义的:

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

    然后可以安全地将newt指针用作t指针;C标准保证结构的第一个元素之前没有填充。

        3
  •  2
  •   rettops    14 年前

    如果T真的以疯狂和未知的方式被广泛使用,那么这样的变化很可能会破坏某些东西。在某个地方,将有一段代码具有局部t声明,而不是使用头文件,或者将“mystruct*”强制转换为“t*”,或者其他同样令人反感的代码。

        4
  •  1
  •   Puppy    14 年前

    是的-当您使用这样的不透明指针时,它与内容无关。只要您的用户只使用不透明指针,您就可以随意处理结构及其实现。

        5
  •  0
  •   Secure    14 年前

    疯狂和未知是不好的。最好的办法是浏览struct t的代码库并检查它是如何使用的,用另一种方法来更改它,看看是否有什么东西中断了……如果代码只使用不透明指针,那么您应该在安全方面。如果代码访问成员,但没有做一些奇怪的事情,那么您也应该是安全的,完全重新编译。

    如果它做了一些奇怪的事情,比如紧身衣的例子,即使是Jukka的小费也可能帮不上忙。代码可以使用sizeof的硬编码值在这些结构的数组中执行指针算术…