Добавление участников к структуре C-стиля и назад совместимости

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

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

С сопровождением функций, которые заполняют d_name любыми потребностями, которые будут помещены там, как

struct T* fill( somethingOrOther* X)

И я хотел бы расширить старый struct+function для включения новой переменной:

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

и новая версия функции также заполнила бы d_type переменную полезными вещами.

Этот тип изменения повредил бы API? Я не мог только использовать новый T вместо старого T и дополнительно получить доступ к новым участникам?

7
задан Cole Johnson 3 October 2015 в 21:34
поделиться

5 ответов

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

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

3
ответ дан 7 December 2019 в 01:15
поделиться

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

2
ответ дан 7 December 2019 в 01:15
поделиться

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

1
ответ дан 7 December 2019 в 01:15
поделиться

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

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

0
ответ дан 7 December 2019 в 01:15
поделиться

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

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

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

4
ответ дан 7 December 2019 в 01:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: