C отрицательный индекс массива - PullRequest
10 голосов
/ 24 октября 2010

это моя структура:

struct Node {
    struct Node* data;
    struct Node* links[4];
}

при условии отсутствия заполнения, гарантированно Node->links[-1] указывает на Node::data?

Ответы [ 7 ]

17 голосов
/ 24 октября 2010

без гарантии;это неопределенное поведение:

  • Зависящее от компилятора заполнение структуры
  • Стандарт определяет индексирование массива только от 0 до длины (включительно)
  • Возможно строгое псевдонимынарушение

На практике вполне возможно, что вы в конечном итоге будете указывать на data, но любые попытки получить к нему доступ приведут к UB.

7 голосов
/ 24 октября 2010

Подпись в массиве определяется в терминах арифметики указателей, и в стандарте C99 это можно сказать об арифметике указателей:

Если и операнд указателя, и результат указывают на элементы тот же объект массива, или один прошлый последний элемент объекта массива, оценка не должна давать над потоком; в противном случае поведение не определено.

Таким образом, доступ к Node->links[-1] (даже просто получение адреса Node->links[-1]), строго говоря, является неопределенным поведением. Таким образом, у вас нет гарантии, что Node->links[-1] получит вас Node::data.

Но, как отмечают многие комментаторы, это будет работать почти всегда. Я все еще считаю это плохой практикой программирования, которой следует избегать. Если не по техническим причинам, то потому, что это требует, чтобы изменения в struct Node могли легко вызвать ошибки, с которыми компилятор вам не поможет. Когда кто-то добавляет что-то между data и links, все таинственным образом нарушается.

3 голосов
/ 24 октября 2010

A union может помочь вам здесь.Как то так:

struct Node {
  union {
    Node *data;
    struct {
      Node *lnk[5];
    } links;
  }
}
2 голосов
/ 24 октября 2010

Я бы сказал да, но почему бы тогда не объявить это как

struct Node {
    struct Node* links[5];
}
0 голосов
/ 24 октября 2010

Это определяется реализацией, в зависимости от того, как реализация формирует структуры и массивы.Тем не менее, до тех пор, пока он имеет одинаковые структуры и массивы, он должен работать.

0 голосов
/ 24 октября 2010

Почти Да

Да, почти наверняка будет указывать на data, но это не может быть точно гарантией.

Вы действительно получаете гарантию, что x[-1] - это то же самое, что и *(x - 1), поэтому, в зависимости от того, что вы указали по адресу x - 1, тогда у вас есть какая-то гарантия.(И не забывайте, что при вычитании из указателей уменьшение уменьшается на размер элемента.)

Хотя другие возражали на основании строгого алиасинга , в данном случаетипы одинаковы, поэтому тщательно продуманные оптимизации не должны удалять ожидаемое поведение.

0 голосов
/ 24 октября 2010

Я думаю, что это так.Но стандарт не гарантирует, что там нет отступов.

Редактировать: но стандарт также гласит, что поведение не определено, если «индекс массива находится вне диапазона, даже если объект явно доступен с данным индексом».

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