Когда вы передаете в функцию указатель на объект (на что угодно), это значит, что вы можете в функции изменять этот объект и все изменения будут видны вызывающему коду.
Если вам надо что бы вызывающий код увидел новый указатель, то передайте в функцию указатель на указатель:
int next_edge(edge_t **out_edge)
{
edge_t * tmp = malloc(sizeof(edge_t));
if(tmp)
{
*out_edge = tmp;
return 1;
}
return 0;
}
Но обычно проще в таком случае возвращать указатель в возвращаемом значении. Вызывающий код может сравнить возвращенное значение с NULL для выяснения того вернула функция нормальный указатель или произошла ошибка. Так делает, например, функция malloc().