void pointer

R

Richard Heathfield

Roman Mashak said:

My question is: is this valid type casting

Your question is: is this valid casting? Type casting is something they
do in Hollywood.
n->data = (void *)data;

Valid but pointless. You're copying a void * to a void *, and in any
case all object pointer types are compatible with void *, so it's a
doubly pointless cast.

Casting is almost always wrong, and the places where it's right are
rarely the places you'd think.
Will I be able to add 'data' of 'int', 'long', 'char' etc. types?

Yes, although your list is merely notatory - it isn't a container.
Beware of that.
Is this right approach?

It depends on what you're trying to achieve.
 
R

Richard Tobin

static list *list_add(list **p, void *data)
{
list *n = malloc(sizeof(list));
n->next = *p;
*p = n;
n->data = (void *)data;
return n;
}

My question is: is this valid type casting

n->data = (void *)data;

There's no need to cast data, it's already of type void *. Assuming that
there's a prototype in scope, the argument will be converted to void *
when list_add() is called.
Will I be able to add 'data' of 'int', 'long', 'char' etc. types? Is this
right approach?

Not portably. You can use any pointer type (except function
pointers), but the effect of converting an arbitrary integer to void *
is undefined. On many systems it will work provided that the integer
type is not bigger than void *. It won't work for floating types.

If you want portability, there are a number of possibilities:

- Always pass a pointer. If you need to store an int, allocate a pointer
to it and pass that.

- Use a union type for data, covering all the possibilities you care
about. You'll need to pass in a value of the union type, not just of
one of the possibilities.

- Pass a pointer and a size to list_add, and allocate the space for
a copy of the pointed-to data.

- If you only care about pointers and integer types, use a sufficiently
long integer type, and cast pointers to that. In C99 intptr_t is
suitable; in C90 there's no guaranteed-big-enough type.

You could provide separate functions list_add_int() and so on that make
these possibilities easier to use.

-- Richard
 
C

CBFalconer

Roman said:
.... snip ...

My question is: is this valid type casting

n->data = (void *)data;

Not really. Just omit the cast. Actually, you should probably
know the type of *data and do a deep copy.
 
S

Stephen Sprunk

Roman Mashak said:
My question is: is this valid type casting

n->data = (void *)data;

It's a valid yet completely unnecessary cast. 'data' is already a void*,
and even if it weren't, any object pointer type can be converted to void*
without a cast (in C; other C-like languages may differ).
Will I be able to add 'data' of 'int', 'long', 'char' etc. types? Is this
right approach?

Not generally. However, you can add pointers to those types:

list_add(&mylist, &intvar);
list_add(&mylist, &longvar);
list_add(&mylist, &charvar);

You may be tempted to try to add "simple" objects directly to the list like
this:

list_add(&mylist, (void *)intvar);
list_add(&mylist, (void *)longvar);
list_add(&mylist, (void *)charvar);

However, that's not portable. If you want to do something like that, you
need to redesign your list to be a container.

S
 
K

Keith Thompson

- If you only care about pointers and integer types, use a sufficiently
long integer type, and cast pointers to that. In C99 intptr_t is
suitable; in C90 there's no guaranteed-big-enough type.
[...]

C99 doesn't guarantee that there's a sufficiently long integer type.
If there isn't, intptr_t won't exist.
 
A

Army1987

Roman Mashak said:
Hello,

I'm studying linked lists and implemented the following:

struct list_node
{
void *data;
struct list_node *next;
};

I intentionally defined 'void *' for data field in order to use various types. Here is a function adding element to linked list:

/* add element in the beginning of list */
static list *list_add(list **p, void *data)
{
list *n = malloc(sizeof(list));
n->next = *p;
*p = n;
n->data = (void *)data;
return n;
}

My question is: is this valid type casting

n->data = (void *)data;

Will I be able to add 'data' of 'int', 'long', 'char' etc. types? Is this right approach?
No. Allocate memory to be pointed to by n->data, and memcpy &data
into it.

Or use a union:

struct list_node {
enum { Int, Long, Char } type;
union {
int Int_; /* or something more decent, since an int */
long Long_; /* will fit in a long anyway, and a single */
char Char_; /* char wastes a lot of space... */
} data;
struct list_node *next;
};

(You can access it as n->data.Int_ for example.)
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Keith said:
- If you only care about pointers and integer types, use a sufficiently
long integer type, and cast pointers to that. In C99 intptr_t is
suitable; in C90 there's no guaranteed-big-enough type.
[...]

C99 doesn't guarantee that there's a sufficiently long integer type.
If there isn't, intptr_t won't exist.

And even if there is, intptr_t needn't exist.
 
K

Keith Thompson

Harald van Dijk said:
Keith said:
- If you only care about pointers and integer types, use a sufficiently
long integer type, and cast pointers to that. In C99 intptr_t is
suitable; in C90 there's no guaranteed-big-enough type.
[...]

C99 doesn't guarantee that there's a sufficiently long integer type.
If there isn't, intptr_t won't exist.

And even if there is, intptr_t needn't exist.

True; all the C99 standard says is "These types are optional."

I'd expect any decent implementation to define them if possible. The
DS9K probably defines them or not depending on the phase of the moon
(and not necessarily *our* moon).
 
R

Roman Mashak

Hello,

I'm studying linked lists and implemented the following:

struct list_node
{
void *data;
struct list_node *next;
};

I intentionally defined 'void *' for data field in order to use various
types. Here is a function adding element to linked list:

/* add element in the beginning of list */
static list *list_add(list **p, void *data)
{
list *n = malloc(sizeof(list));
n->next = *p;
*p = n;
n->data = (void *)data;
return n;
}

My question is: is this valid type casting

n->data = (void *)data;

Will I be able to add 'data' of 'int', 'long', 'char' etc. types? Is this
right approach?

Thank you.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top