В этом интервью Slashdot Линус Торвальдс цитирует слова:
Я видел слишком много людей, которые удаляли односвязную запись списка, отслеживая запись «prev», а затем удаляли запись, делая что-то вроде
if (prev)
prev-> next = entry-> next;
иначе
list_head = entry-> next;и всякий раз, когда я вижу такой код, я просто говорю: «Этот человек не понимает указателей». И это, к сожалению, довольно часто.
Люди, которые понимают указатели, просто используют «указатель на указатель записи» и инициализируют его адресом list_head. И затем, проходя по списку, они могут удалить запись без использования каких-либо условий, просто выполнив «* pp = entry-> next».
Как разработчик PHP, я не касался указателей с момента введения в Си в университете десять лет назад. Тем не менее, я чувствую, что это тип ситуации, с которой я, по крайней мере, должен быть знаком. О чем говорит Линус? Если честно, если бы меня попросили реализовать связанный список и удалить элемент, то вышеупомянутый «неправильный» путь - это то, как я бы поступил. Что мне нужно знать, чтобы кодировать, как лучше всего говорит Линус?
Я спрашиваю здесь, а не о переполнении стека, поскольку у меня фактически нет проблем с этим в производственном коде.
prev
, а не весь узел, вы можете просто сохранить местоположениеprev.next
, так как это единственное, что вас интересует. Указатель на указатель. И если вы сделаете это, вы избежите глупостиif
, так как теперь у вас нет неловкого случаяlist_head
быть указателем извне узла. В этом случае указатель на начало списка семантически совпадает с указателем на следующий узел.