это моя структура:
struct Node {
struct Node* data;
struct Node* links[4];
}
Предполагая, что нет отступов, Node->links[-1]
гарантированно указывает на Node::data
?
это моя структура:
struct Node {
struct Node* data;
struct Node* links[4];
}
Предполагая, что нет отступов, Node->links[-1]
гарантированно указывает на Node::data
?
Нет гарантии; это поведение undefined:
На практике, вполне возможно, что вы укажете на data
, но любые попытки доступа к нему приведут к UB.
Подстрока массива определяется в терминах арифметики указателя, а в стандарте C99 это говорит об арифметике указателя:
Если и операнд указателя, и результат указывает на элементы тот же объект массива или один прошлый последний элемент объекта массива, оценка не должна давать над потоком; в противном случае поведение undefined.
Таким образом, доступ к Node->links[-1]
(даже просто получение адреса Node->links[-1]
) - это поведение undefined, строго говоря. Поэтому у вас нет гарантии, что Node->links[-1]
получит вас Node::data
.
Но, как упоминают многие комментаторы, это будет работать почти всегда. Я все еще считаю это плохой практикой программирования, которой следует избегать. Если это не техничность, то из-за того, что изменения в struct Node
могут привести к ошибкам, которые компилятор вам не поможет. Когда кто-то добавляет что-то между data
и links
, все будет таинственно ломаться.
A union
может помочь вам здесь. Что-то вроде этого:
struct Node {
union {
Node *data;
struct {
Node *lnk[5];
} links;
}
}
Я бы сказал, да, но почему бы не объявить его как
struct Node {
struct Node* links[5];
}
Да, он почти наверняка укажет на data
, но это может быть не совсем гарантия.
Фактически вы получаете гарантию, что x[-1]
- это то же самое, что и *(x - 1)
, поэтому, в зависимости от того, что вы указали по адресу x - 1
, у вас есть своего рода гарантия. (И не забывайте, что при вычитании из указателей декремент зависит от размера элемента.)
Хотя другие возражали по принципу строгой псевдонимы, в этом случае типы одинаковы, поэтому сложные оптимизации не должны устранять ожидаемое поведение.
Думаю, что да. Но стандарт не гарантирует, что нет прокладки.
Изменить: но стандарт также говорит, что поведение undefined, если "Индекс массива вне диапазона, даже если объект, по-видимому, доступен с заданным индексом".
Это реализация определена в зависимости от того, как структуры и массивы реализации реализуются. Тем не менее, до тех пор, пока он создает структуры и массивы одинаково, он должен работать.