Вы должны использовать двойной указатель в этом например, потому что вы также хотели бы изменить начальный узел вашего списка. Таким образом, в основном, когда вы вставляете новый элемент, вы также хотите сделать узел, который содержит его первым в списке.Если вы передаете только один указатель (list *l
) и назначаете ему вновь созданный узел (p
), изменения (а по изменениям означают тот факт, что он будет первым узлом списка) будут доступны только внутри вашего функции и не будет распространяться вне него.
Чтобы сделать его более ясным, если вы принимаете в простой указатель (list *l
) вы в основном копирование адреса, сохраненную list*
переменной, которая сидит за пределами функции, во вновь созданном указателе (параметр l
) , Таким образом, переменная l
внутри вашей функции является другим указателем (другое место в памяти по сравнению с переменной указателя вне вашей функции), содержащей тот же адрес, что и указатель вне функции. Вот почему назначение вновь созданного элемента на этот l
однократный указатель только сделает вновь вставленный элемент первым только локальным (область функций).
По сравнению с альтернативным методом, когда вы берете двойной указатель (так list **l
), действительно происходит то, что, передавая внешнюю переменную указателя функции, вы фактически передаете адрес внешнего указателя, не путать с адресом, который содержит указатель. (позаботьтесь, так как вам нужно будет вызвать функцию примерно так: insert(&l, 2)
). Таким образом, вы по-прежнему будете иметь адрес, содержащий внешний указатель, разыменовывая его и используя его как rvalue (p->next = *l
), и в то же время у вас есть адрес внешней переменной, поэтому, когда вы делаете *l = p
(используется уведомление *l
как lvalue здесь), вы на самом деле разыгрываете двойной указатель, и в результате вы получите адрес реальной переменной (внешний), назначив ей вновь созданный узел. Другими словами, вы фактически устанавливаете вновь созданный узел в качестве стартового узла, но на этот раз также вне функции.
Действительно надеюсь, что это не очень запутывает.
Это добавляет новый узел в список (фактически, * стек *). * Caller * должен получить указатель на новый заголовок списка * как-то *. Это один из способов сделать именно это. Другим является то, что функция всегда возвращает головку списка. – WhozCraig