Добавление членов в структуру в стиле C и обратная совместимость - PullRequest
7 голосов
/ 22 июля 2010

Скажем, у меня есть структура, определенная где-то глубоко в низкоуровневом коде, который используется повсеместно самыми безумными и неизвестными способами:

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 ]

4 голосов
/ 22 июля 2010

Возможно, имеет смысл расширить ваши структуры следующим образом:

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

Тогда вы можете безопасно использовать указатель newT в качестве указателя T; стандарт C гарантирует, что перед первым элементом структуры нет заполнения.

3 голосов
/ 22 июля 2010

Пока код, использующий этот API, получает только T объекты в виде указателей, возвращаемых библиотекой, и не объявляет их сам, malloc их сам (используя sizeof(struct T)) или выполняет что-либо еще, что зависит отразмер структуры, то это должно быть хорошо.Если вызывающий код получил доступ к содержимому структуры, вам необходимо убедиться, что вы добавили новые члены в конец структуры.

Одно из возможных дополнительных соображений - зависит ли какой-либо код от d_name в концеструктуры, чтобы выделить пространство и хранить большие имена, если объявленный размер не подходит.Я упоминаю об этом только потому, что имена членов предполагают, что структура похожа на dirent, и это традиционная практика для dirent.

2 голосов
/ 22 июля 2010

Если T действительно используется повсеместно сумасшедшим и неизвестным образом, то подобное изменение может что-то сломать. Где-то будет фрагмент кода, который имеет локальную декларацию T вместо использования вашего заголовочного файла, или преобразует mystruct * в T *, или что-то в равной степени отвратительное.

1 голос
/ 22 июля 2010

Да - когда вы используете такой непрозрачный указатель, это не имеет отношения к содержимому. Пока ваши пользователи когда-либо использовали непрозрачные указатели, вы можете разбираться со структурой и ее реализацией, как вам угодно.

0 голосов
/ 22 июля 2010

Сумасшедший и неизвестный не хорошо.Лучше всего сканировать кодовую базу на наличие структуры T и изучить, как она используется, с альтернативным подходом к ее изменению и посмотреть, не сломалось ли что-то ... Если код использует только непрозрачные указатели, вы должны быть на безопасной стороне.Если код обращается к членам, но не делает что-то странное, вы тоже должны быть в безопасности, с полной перекомпиляцией.

Если он делает что-то странное, например, примеры реттопов, даже совет Юкки может не помочь.Код может использовать жестко закодированное значение для sizeof, чтобы сделать арифметику указателей в массиве этих структур ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...