9

I am beginner in C programming and I am studying on Linked Lists. I am trying to create a Linked List which is gonna display the letters in correct order. The program enables the user to insert a character in the list in alphabetical order or to delete a character from the list. So, I follow an example to a point but there is something that I cannot understand.

Here is the first part of the code:

#include <stdio.h>
#include <stdlib.h>

struct listNode {
    char data;
    struct listNode *nextPtr;
};

typedef struct listNode ListNode;
typedef ListNode *ListNodePtr;

After that part, program starts with the function prototype. I know the usage of typedef in the second line from the bottom. But what I don't know is, the last line of the code which contains:

typedef ListNode *ListNodePtr;

What does that mean?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Alexa
  • 103
  • 1
  • 2
  • 8
  • 1
    See [Is it a good idea to `typedef` pointers?](http://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers) for a strong suggestion that the last line is not beneficial. At least in your case it clearly includes the `Ptr` in the name, but `*` is as clear as `Ptr` too. – Jonathan Leffler Oct 17 '15 at 16:08
  • I always wounder what would it be good for the suffix/prefix a typename with `Ptr` or similar instead of just putting the `*` in front of the typename. The latter is much more explicit and pollutes namespace less, if you would use this consequently (and if not, what would it be good for anyway?). – too honest for this site Oct 17 '15 at 16:26
  • @Olaf I guess we had a similar discussion just a few days ago, and there's *one* possible good use for `typedef`ing a pointer, that is when client code gets it as an *opaque handle* and really shouldn't know it *is* a pointer. (e.g. because it could change to an `int` in a later version without introducing breaking changes in the API) This, of course, is a corner case and of course you **wouldn't** use a `Ptr` suffix then ... –  Oct 17 '15 at 16:36
  • @FelixPalmen: [History repeating](https://www.youtube.com/watch?v=yzLT6_TQmq8). It comes up ever few weeks here. But I'm actually against such pointers, too. Note this does not include opaque/`typedef`ed `struct`s , which is very useful. – too honest for this site Oct 17 '15 at 16:39
  • 1
    @Olaf like this song, long time ago ... still I'm not strictly against that, there ARE situations where you need an *opaque handle* and making it a pointer *could* be an *implementation detail*. But in the general case, `typedef`ing pointers really is a no-no :) –  Oct 17 '15 at 16:42
  • @Olaf as an example coming to mind right now: consider `va_list`. There are architectures where `va_list` being a pointer is the straight forward choice :) Still you don't want client code to rely on that. –  Oct 17 '15 at 16:44
  • In general (maybe I should start some code blog :o) ... If your reason to `typedef` a pointer is a good application of the *information hiding principle*, **then** do it. In the majority of cases (appending something like `Ptr` to the name is a clear sign of "smell"), it's just bad .... –  Oct 17 '15 at 16:51
  • @FelixPalmen: `va_list` is a very special case, as it is not necessarily just a pointer. So, yes, that might be a valid application: if the type is not necessarily a pointer, but we are talking about typedefing explicitly pointers. A counter-example: `FILE` which is only passed by pointers in user code, so could well be a `typedef FILE *`.."appending something like Ptr to the name is a clear sign of "smell"" let's leave it at that! – too honest for this site Oct 17 '15 at 16:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92587/discussion-between-felix-palmen-and-olaf). –  Oct 17 '15 at 17:16
  • @FelixPalmen: No time now. It will eventually pop up again;-) – too honest for this site Oct 17 '15 at 17:23

3 Answers3

23

Short version:

typedef ListNode *ListNodePtr;

defines ListeNodePtr as a pointer to ListNode.

You may wonder why the asterisk is "sticking" to ListNodePtr here. That's because in C declarations, being a pointer is considered a type modifier, so in a declaration, it's part of the declarator (the identifier of the variable or typedef'd type).(*) This is relevant as soon as you have multiple declarations in a single line, e.g. the following:

int *a, b;

would define a pointer to int a and a plain int b.

You could write it as

int* a, b;

but that would be very confusing, because b would still not be a pointer.

All that being said, I personally consider it bad style to typedef a pointer, because as a C programmer, you know the meaning of an asterisk. Hiding it behind a typedef (and as done here, replacing it by some non-standard suffix like "Ptr") just makes the code harder to read for others.

(*) added footnote here: the reasoning behind this design is that declarations should look the same as usage. *a dereferences a pointer, so *a should as well declare a pointer.

  • 2
    And to add to your footnote: When the typedef type is a structure type, then `ListNode *ptr` tells you to use `ptr->nextPtr` rather than the stilted but valid `(*ptr).nextPtr`, or in a slightly more complex expression, `ptr->nextPtr->data` instead of `(*(*ptr).nextPtr).data`, etc. Of course, you'd have checked that `ptr->nextPtr` is not null before trying that. – Jonathan Leffler Oct 17 '15 at 16:10
  • @JonathanLeffler yes, that's what I'm after with my *opinion* in this answer ... make pointers explicit. Thanks for adding more reasoning to it. –  Oct 17 '15 at 16:15
4
typedef struct listNode ListNode;

The first line means ListNode will represent struct listNode.

typedef ListNode *ListNodePtr;

The second line means ListNodePtr will represent ListNode * which is a pointer to ListNode.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
Haris
  • 12,120
  • 6
  • 43
  • 70
2

A ListNodePtr holds a pointer to a ListNode. So if you unravel the typedefs, it's short for: struct listNode *.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
GaryTR
  • 96
  • 6