Рассмотрим следующую структуру C99, заканчивающуюся элементом гибкого массива:
struct hdr
{
size_t len;
size_t free;
char buf[];
};
len
например, доступ к нему осуществляется с помощью встроенной функции (для помещения в файл заголовка), например buf
в качестве аргумента:
static inline size_t slen(const char *s)
{
struct hdr *h = (struct hdr*)(s - (int)offsetof(struct hdr, buf));
return h->len;
}
Это часть библиотеки, которая должна быть скомпилирована с помощью компилятора Си. Тем не менее, я хотел бы получить доступ к этой библиотеке из C ++; это по существу означает, что соответствующий заголовочный файл (с надлежащим extern "C" {...}
guard) должен быть действующим кодом C ++. Возможным решением является определение slen
функция в теле исходного кода, полностью избегая встроенного кода, но это не оптимально.
Моя идея состоит в том, чтобы определить фиктивную структуру C ++, которая является действительной, и которую я могу как-то сопоставить hdr
например,
struct cpp_hdr
{
size_t len;
size_t free;
char buf[1];
}
Обратите внимание, что я хочу получить только правильные (отрицательные) значения смещения для len
а также free
; нет доступа к buf
предназначен.
Теперь мой вопрос: есть ли гарантия того, что
static inline size_t slen(const char *s)
{
struct cpp_hdr *h = (struct cpp_hdr*)(s - (int)offsetof(struct cpp_hdr, buf));
return h->len;
}
работает, дает тот же результат?
В формальном ничего не гарантировано, потому что C ++ не поддерживает гибкие массивы: такого понятия нет, такого синтаксиса нет.
На практике компиляторы не делают ничего без прямой причины. Так что не будет введено ни одного волнистого дополнения. Однако, чтобы сделать это совершенно ясным, я бы использовал размер массива, например 666 вместо 1, что лучше работает в более общем случае (например, небольшой массив 1 char
может быть перемещен в другую область заполнения в какой-либо другой структуре). В качестве преимущества умный код для размещения больше не будет выглядеть просто. Так что это должно быть сделано правильно.
Все это говорит, это звучит как 16-битная Windows BSTR
кроме BSTR
нет такого разрыва между длиной и строковыми данными. Подумайте, не является ли эта библиотека просто чьим-то безосновательным переизобретением колеса. Если это так, я предлагаю использовать оригинальное колесо вместо.
Предполагая, что библиотека была скомпилирована другим компилятором, не гарантируется, что смещение будет таким же. Практически, это должно работать большую часть времени.
Если вы работаете с конкретным компилятором, вы можете использовать отладчик и настроить вычисление смещения для этого компилятора и сделать утверждение в начале, чтобы убедиться, что ваше предположение (настройка) остается верным, если позже вы решите перейти на другой компилятор или более новую версию. ,