Reputation: 33
Is there any difference (performance / correctness / good practice) between:
Option 1:
typedef struct node{
int value;
struct node *next;
}*Node;
typedef struct linkedlist{
Node head;
}*LinkedList;
Option 2:
typedef struct node{
int value;
struct node *next;
}*Node;
Node head = NULL;
And how can "double-pointer" scheme integrate both definitions?
Upvotes: 0
Views: 87
Reputation: 11
Contrary to what the comments say, it's not always a bad idea to typedef
a pointer. There are some cases when you want to hide implementation details and provide functionality through a handle. In these situations it's quite common to see what's called an opaque pointer type.
Example:
In LinkedList.h
typedef void *LinkedList;
LinkedList LinkedList_Create();
void LinkedList_AddFirst(LinkedList list, void *element);
In LinkedList.c
struct linkedList {
/* head, tail, size, ... */
};
LinkedList LinkedList_Create() {
struct linkedList *plist = malloc(sizeof(struct linkedList));
/* error checking, initialization */
return plist;
}
void LinkedList_AddFirst(LinkedList list, void *element) {
struct linkedList *plist = (struct linkedList *) list;
/* your code here */
}
The downside of this approach is that you're required to explicitly cast the typedef
'd pointer to your internal type but this will not result in worse performance since C does not provide runtime type checking.
From a best practices point of view, it's usually best to not typedef
a pointer if you don't need to hide implementation details. Sure, it might make your code more verbose but that way you always know what type you're dealing with. Generally, a typedef
should not hide the underlying type, but simply provide an alias for it.
If you're interested in knowing more about best practices in C, I refer you to Linux kernel's coding style guide, which you can find here.
Upvotes: 1
Reputation: 14390
Yes, there seem to be a difference. First of all you haven't shown how you intend to use LinkedList
, but anyway there is one more level of indirection needed to get to the data in the first option.
Let's assume that you in option one would use LinkedList
as:
LinkedList lst;
then in order to get the first node in the list (or NULL
if it's empty) you would have to use lst->head
, while in the second option you just would use head
directly. This would mean that the second option is slightly more efficient (in some cases).
However in the second option you have to send a pointer to head
in order to pass it to a function that modifies the list as a whole. For example a function that empties a list must be able to modify the pointer to the head of the list in order to set it to NULL
(yes it must also free
the nodes, but that's beside the point). In the first option you can do this simply by arg->head = NULL
, but in the second option you must send Head*
to the function for it to be able to clear the head pointer. In this scenario there would be the same number of indirections to get to the elements.
Upvotes: 0