1

I'm trying to implement a generic linked list. The struct for the node is as follows -

typedef struct node{
        void *data;
        node *next;      
};

Now, when I try to assign an address to the data, suppose for example for an int, like -

int n1=6;
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data=&n1;

How can I get the value of n1 from the node? If I say -

cout<<(*(temp->data));

I get -

`void*' is not a pointer-to-object type 

Doesn't void pointer get typecasted to int pointer type when I assign an address of int to it?

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
theharshest
  • 7,767
  • 11
  • 41
  • 51
  • 4
    Why are you using malloc and C-style pointers in a C++ program ? – Paul R May 16 '12 at 08:50
  • if this is not an exercise, stop reinventing the wheel and use e.g. linked list provided in [glib](http://developer.gnome.org/glib/2.32/glib-Singly-Linked-Lists.html) – Bort May 16 '12 at 08:52
  • @PaulRL The OP mentions C as the language of implementation in his question title. – dirkgently May 16 '12 at 08:55
  • 1
    Can we please keep cout/printf out of question here? It's just about dereferencing void pointer and yes its an exercise. – theharshest May 16 '12 at 08:57
  • @DavidHeffernan: True. That is what should be pointed out then. Using `malloc` in C++ is just fine. This trend of looking down on `malloc` and `free` in C++ has become sort of a style statement that I don't agree with. – dirkgently May 16 '12 at 09:00
  • 1
    If you want to make your linked list truly generic then you should use templates. If you want each of your node to point to different object (thru data pointer), then you might want to implement some kind of Variant functionality, ie. add integer field that will contain additional information on the type of data, you will use it for casting, or use Boost/Any – marcinj May 16 '12 at 09:08
  • Ok, then ignore my comment, as a comparison to C++ you might want to take a look at that glib code to get an idea how generic storage types have been implemented in C. – Bort May 16 '12 at 09:11

4 Answers4

12

You must first typecast the void* to actual valid type of pointer (e.g int*) to tell the compiler how much memory you are expecting to dereference.

iammilind
  • 68,093
  • 33
  • 169
  • 336
user703016
  • 37,307
  • 8
  • 87
  • 112
  • So, in this case of generic linked list, each node has a different type of data like int or char or char*. So, to get the value of each data I need to typecast? That means I can't loop over the linked list and get the data values in a generic way? – theharshest May 16 '12 at 09:08
  • You need to either typecast (knowing the underlying type) or create a generic container that knows the underlying type and can properly return its value. – user703016 May 16 '12 at 09:10
  • @theharshest, for generic linked list you should be using templatized constructs, e.g. `std::list` – iammilind May 16 '12 at 09:10
  • If nodes of the same list do not share a common type you are probably going to have to "box" them (make their values be held by specialized classes derived from a base one). – user703016 May 16 '12 at 09:20
4

A void pointer cannot be de-referenced. You need to cast it to a suitable non-void pointer type. In this case, int*

cout << *static_cast<int*>(temp->data);

Since this is C++ you should be using C++ casts rather than C styles casts. And you should not be using malloc in C++, etc. etc.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • ...and if you're writing a 'generic' linked list you should be using generics. Or as we call them, templates. :-) – Grimm The Opiner May 16 '12 at 09:00
  • I wonder why this answer and the accepted answer have downvotes. – David Heffernan May 16 '12 at 12:02
  • I think it might be because even though you answered the question perfectly correctly as it was asked, using that answer would still end up with bloody awful code! :-) – Grimm The Opiner May 17 '12 at 08:36
  • @user That could explain upvotes to other answers. Downvoting answers that address the question as asked is just bizarre in my view. – David Heffernan May 17 '12 at 08:45
  • I could imagine a down vote or two from "should be using C++ casts rather than C style". Seeing as how it ultimately matters little and has even less to do with the question. Just a guess. – Josh C Jul 29 '15 at 23:28
2

A void pointer cannot be dereferenced. You need to cast it to a suitable non-void pointer type. The question is about C++ so I suggest considering using templates to achieve your goal:

template <typename T> struct node
{
   T *data;
   node<T> *next;      
};

then:

int n1=6;
node<int> *temp = new node<int>();
temp->data=&n1;

And finally:

cout << (*(temp->data));

Typecasting is possible, but that will be a C-style type-unsafe solution and not a C++ one.

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
  • 2
    The `typedef` is unnecessary in C++, and since we are taking templates... Also, it seems rather useless to have data be `T*`, a simple `T` would suffice. – Matthieu M. May 16 '12 at 09:58
  • 1
    Fixed. T* is used as provided by the original author. – Sergey K. May 16 '12 at 10:00
  • Also, use `std::unique_ptr> next;` (or preferably `boost::optional> next;`) instead. And the first node need not be dynamically allocated; just use `node temp;`. –  May 16 '12 at 11:08
  • 1
    @SergeyK.: I disagree. The OP does not use `T*`, he uses `void*`. The important difference is that polymorphism requires indirection (an issue of size), but with parametric code there is no longer any polymorphism necessary. Therefore `T` is a viable substitution. – Matthieu M. May 16 '12 at 11:21
  • In case of T you have to store a copy (value), in case of T* the value can be shared. Though, it does not matter for integral types. – Sergey K. May 16 '12 at 14:23
  • I'd store data as `T`, and let the user of the class decide whether to store pointers or objects. – Grimm The Opiner May 17 '12 at 08:39
0

Typecast temp->data to int and then print.

cout<<*((int *)temp->data);
VenkatH
  • 159
  • 1
  • 7