Несколько лет назад Линус Торвальдс выступил с речью Теда, где продемонстрировал реализацию связанного списка, в которой удаляются посторонние тесты с использованием указателей на указатели, которые он считает «хорошим вкусом». Простой пример ниже:
#include <stdio.h>
#include <stdlib.h>
struct list_entry {
int val;
struct list_entry *next;
};
void list_insert(struct list_entry **head, int val)
{
while (*head)
head = &(*head)->next;
*head = calloc(1, sizeof(**head));
(*head)->val = val;
}
int main(int argc, char *argv[])
{
struct list_entry *head = NULL;
list_insert(&head, 0);
list_insert(&head, 1);
printf("Entry 1: %d\n", head->val);
printf("Entry 2: %d\n", head->next->val);
}
Мне удалось создать нечто похожее на эту работу в фортране благодаря использованию рекурсивной list_insert
и семантики вызова по фортрану:
module list_type
implicit none
type :: list
integer :: val
type(list), pointer :: next => null()
end type list
contains
recursive subroutine list_insert(lst, val)
type(list), pointer, intent(inout) :: lst
integer :: val
!-
if (associated(lst)) then
call list_insert(lst%next, val)
return
else
allocate(lst)
lst%val = val
end if
end subroutine list_insert
end module list_type
program list_test
use list_type
implicit none
type(list), pointer :: head => null()
call list_insert(head, 0)
call list_insert(head, 1)
call list_insert(head, 2)
print *, head%val
print *, head%next%val
print *, head%next%next%val
end program list_test
Есть ли способ заставить эту работу работать без рекурсии? До сих пор все мои попытки заканчивались неудачей.
РЕДАКТИРОВАТЬ: Вот пример моего итеративного подхода не работает
module list_type
...
type :: list_ptr
type(list), pointer :: p
end type list_ptr
contains
...
subroutine list_insert_iter(lst, val)
type(list), pointer, intent(inout) :: lst
integer :: val
!-
type(list_ptr) :: walker
walker%p => lst
do while (associated(walker%p))
walker%p => lst%next
end do
allocate(walker%p)
walker%p%val = val
end subroutine list_insert_iter
end module list_type
program list_test
use list_type
implicit none
type(list), pointer :: head => null()
call list_insert_iter(head, 0)
if (.not.associated(head)) stop "FAIL"
end program list_test