void add_to_list(struct list *l, int newval)
Your function is declared as void
. This means there's no way for
your function to signal an error. Not a problem for sample code,
but definitely something you should at least be aware of.
if (!l) return; //my fried said that I should add this,
//and should it be if(l == NULL) rather than if(!l)?
The construct (!l)
is completely equivalent to (l != NULL)
. This
is because NULL
is defined to be "a null pointer constant", and
"null pointer constant" is "An integer constant expression with
the value 0, or such an expression cast to type void *
". In other
words, NULL
evaluates to zero.
while(l->next !=NULL) // I am pretty sure that this while loop is correct
l=l->next;
Yes, this while
loop is correct. When the loop completes, l
will
be pointing at the last element in the list.
l->next = malloc(sizeof(int)) //hmm... is this correct way to allocate memory
Your allocation is almost right. You're allocating enough storage to
hold one int
, but you really need enough storage to hold one
struct list
. use l->next = malloc(sizeof(struct list));
instead.
l->next->val = newval; //not sure about this
No error here. This is exactly as correct as the next line is.
l->next->next = NULL; //This should be fine
Yes, this is fine..
However, while this section of code is mostly correct, barring the malloc()
that was already covered,
l->next = malloc(sizeof(int)) //hmm... is this correct way to allocate memory
l->next->val = newval; //not sure about this
l->next->next = NULL; //This should be fine
the method used here is slightly unusual. This is because
when you allocate the new memory, you're assigning the pointer
directly to l->next
and then initializing it.
What is more commonly done is todeclare a pointer such as
struct list *tmp = NULL
at the beginning of the function,
and when allocating, assign the new memory to tmp
. Then,
initialize the new list element pointed at by tmp
, and
only then add the now-initialized new list element to the
end of the list. While this involves slightly more code,
it separates the two steps of creating the new list element
and of adding the element to the end of the list.
void add_to_list(struct list *l, int newval)
{
struct list *tmp = NULL;
if (!l) return; // If no valid list, return.
tmp = malloc(sizeof(struct list)); // Allocate new list element
tmp->val = newval; // and fill it up.
tmp->next = NULL; // End of the list always points nowhere.
while(l->next !=NULL) // find end of list.
l=l->next;
l->next = tmp; // Attach new list element to end.
return;
}
Also, doing it this way avoids the potential confusion that can arise
from assigning values through the l->next
pointer.