Passing void pointer to p_thread that is a Char

J

Juggernaut

I am trying to create a p_thread
pthread_create(&threads[k], &attr, Teste, (void *)var);
where var is a char variable.
But this doesnt't work, I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Now I thought that when it was a void I could pass anything? Thing is it
works when I use an int, but in this case I wanted to use a char. It wouldnt
be hard to work around it, but it annoys me because I've heard anything can
be passed as long as its a void.

I have remembered to declare the function:
void *Teste(void *var)

and in the main method that created the thread I have declared the var
variable :
char var;
var = 'A'

and the function itself: void *Teste(void *var)

Now If I were to change the char declaration of var to f.example:
int var;
var = 1;

It works.

Now as I said I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Why? And where does the pointer from integer come from? Theres no integer
involved, Im trying to pass a void thats a char.

If anyone can help me I would highly apriciate it.
 
J

Jason

Juggernaut said:
I am trying to create a p_thread

p_threads are a bit OT...
pthread_create(&threads[k], &attr, Teste, (void *)var);
where var is a char variable.
But this doesnt't work, I get this message:
test.c:58: warning: cast to pointer from integer of different size.

and in the main method that created the thread I have declared the var
variable :
char var;
var = 'A'

Is it really your intention to convert the (probably) 8 bit char value
contained within var into a (probably) 32 bit memory address, and then
to save this address as a void* ?

Now If I were to change the char declaration of var to f.example:
int var;
var = 1;

It works.

This works beause the int is (probably) a 32 bit value.
Now as I said I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Why? And where does the pointer from integer come from? Theres no integer
involved, Im trying to pass a void thats a char.

If anyone can help me I would highly apriciate it.

What you really want to do is (void *)&var. This will achieve, I
believe, what you are trying to do.

-Jason
 
J

Juggernaut

What you really want to do is (void *)&var. This will achieve, I believe,
what you are trying to do.

In the function or the p_thread_create?

The reason for the void thing is because, if I've understood correctly,
p_thread creates demands a void variable.

And I need the passed value to be a char.



>Jason said:
I am trying to create a p_thread

p_threads are a bit OT...
pthread_create(&threads[k], &attr, Teste, (void *)var);
where var is a char variable.
But this doesnt't work, I get this message:
test.c:58: warning: cast to pointer from integer of different size.

and in the main method that created the thread I have declared the var
variable :
char var;
var = 'A'

Is it really your intention to convert the (probably) 8 bit char value
contained within var into a (probably) 32 bit memory address, and then
to save this address as a void* ?

Now If I were to change the char declaration of var to f.example:
int var;
var = 1;

It works.

This works beause the int is (probably) a 32 bit value.
Now as I said I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Why? And where does the pointer from integer come from? Theres no integer
involved, Im trying to pass a void thats a char.

If anyone can help me I would highly apriciate it.

What you really want to do is (void *)&var. This will achieve, I
believe, what you are trying to do.

-Jason
 
J

Jason

Juggernaut said:
believe,
what you are trying to do.

In the function or the p_thread_create?
Yep


The reason for the void thing is because, if I've understood correctly,
p_thread creates demands a void variable.

void * you mean...
And I need the passed value to be a char.

The function expects a void*, but you want to give it a char. The only
choice you have is to give it the _address_ of your char variable. This
_address_ gets cast into a void*.

For example:

char var;
var = 'A';

Internally var could be an 8 bit section of RAM at address 0x123ABC
(I'm making up the address, but you get the point).

If you pass (void *)&var then you are saying (void *)0x123ABC. But, if
you simply type (void *)var then what you are really doing is taking
the char value of 'A' (which is 0x41, or 65) and casting _that_ into a
void *.

Luckily, the compiler catches the error and warns you that you are
using a small integer value (char) as the source for conversion.

Read up on memory addresses, pointers, and such. It sounds like you are
still a bit shaky.

-Jason
 
J

Juggernaut

Thanks
Read up on memory addresses, pointers, and such. It sounds like you are
still a bit shaky.

Yes, I'm new to C and in the past I've programmed in Java so pointers and
such is new to me.
 
K

Keith Thompson

Juggernaut said:
I am trying to create a p_thread
pthread_create(&threads[k], &attr, Teste, (void *)var);
where var is a char variable.
But this doesnt't work, I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Right, because you're casting to a pointer type (void*) from an
integer of a different size (char). (Remember that char is an integer
type.)

pthread_create is strictly off-topic here, but the issues you're
running are really language issues.

Suppose you have a function called foo_create declared like this:

int foo_create(foo_t *foo,
something_t *something,
void *(*start_routine)(void *),
void *arg);

(You may notice a resemblance to pthread_create, which I won't discuss
further since it's off-topic.)

The foo_create() function attempts to create a "foo" (whatever that
may be). Part of the process of creating a "foo" involves calling a
user-defined start routine. The third argument to foo_create is a
pointer to this start routine (a function that takes a single void*
argument), and the fourth argument is the void* value to be passed to
the start routine.

Why void*? Because void* is a generic pointer type. Any object
pointer type can be converted to void*, and vice versa; a void*
pointer can point to any object of any type. foo_create() doesn't
have to know what kind of data you want to pass to your start
function; only the function itself has to know. This is similar to
the method used by the standard qsort() function, which takes a
pointer to a comparison function that in turn takes two void*
arguments, pointers to the values being compared.

You can't call your start routine directly; you call foo_create(),
which calls your start routine. So any information you want to pass
to your start routine has to go through a parameter of type void*.

Converting between integer types and pointer types, as you've
attempted to do, is seldom a good idea. If you really want your start
routine to accept a char argument, you can probably get away with
converting the char value to void*, and letting the start routine
convert the void* back to char, but that's ugly. C has little enough
type checking as it is; subverting it is likely to get you into
trouble. (Note that your start routine can't be declared to take a
char argument; for compatibility with the definition of foo_create(),
it has to accept a void* argument.)

The idea of the void* argument isn't to squeeze information *into* the
pointer argument, it's to use it to *point to* the information you
want. If you need your start routine to accept a larger amount of
information, you can wrap it all in a structure and pass a pointer to
the structure. You'd convert the structure pointer to void* so you
can pass it to foo_create(), foo_create would pass the void* to your
start routine, and your start routine would then convert it from void*
to a structure pointer, which can be used to access the members. (The
conversions can be done implicitly; converting between void* and
another object pointer type doesn't require an explicit cast.)

But if you just want to pass a single char value to your start
routine, the cleanest way to do it is to pass a pointer to a char
object. Your start routine can then convert its void* argument to
char* and dereference it to obtain the original char value.
 
J

Juggernaut

Thanks for the thourough and absolutely great explanation.

Btw, I'll try to read the FAQ for this group before next time I post. :)


Btw, is there a FAQ I can read for this group?
Keith Thompson said:
Juggernaut said:
I am trying to create a p_thread
pthread_create(&threads[k], &attr, Teste, (void *)var);
where var is a char variable.
But this doesnt't work, I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Right, because you're casting to a pointer type (void*) from an
integer of a different size (char). (Remember that char is an integer
type.)

pthread_create is strictly off-topic here, but the issues you're
running are really language issues.

Suppose you have a function called foo_create declared like this:

int foo_create(foo_t *foo,
something_t *something,
void *(*start_routine)(void *),
void *arg);

(You may notice a resemblance to pthread_create, which I won't discuss
further since it's off-topic.)

The foo_create() function attempts to create a "foo" (whatever that
may be). Part of the process of creating a "foo" involves calling a
user-defined start routine. The third argument to foo_create is a
pointer to this start routine (a function that takes a single void*
argument), and the fourth argument is the void* value to be passed to
the start routine.

Why void*? Because void* is a generic pointer type. Any object
pointer type can be converted to void*, and vice versa; a void*
pointer can point to any object of any type. foo_create() doesn't
have to know what kind of data you want to pass to your start
function; only the function itself has to know. This is similar to
the method used by the standard qsort() function, which takes a
pointer to a comparison function that in turn takes two void*
arguments, pointers to the values being compared.

You can't call your start routine directly; you call foo_create(),
which calls your start routine. So any information you want to pass
to your start routine has to go through a parameter of type void*.

Converting between integer types and pointer types, as you've
attempted to do, is seldom a good idea. If you really want your start
routine to accept a char argument, you can probably get away with
converting the char value to void*, and letting the start routine
convert the void* back to char, but that's ugly. C has little enough
type checking as it is; subverting it is likely to get you into
trouble. (Note that your start routine can't be declared to take a
char argument; for compatibility with the definition of foo_create(),
it has to accept a void* argument.)

The idea of the void* argument isn't to squeeze information *into* the
pointer argument, it's to use it to *point to* the information you
want. If you need your start routine to accept a larger amount of
information, you can wrap it all in a structure and pass a pointer to
the structure. You'd convert the structure pointer to void* so you
can pass it to foo_create(), foo_create would pass the void* to your
start routine, and your start routine would then convert it from void*
to a structure pointer, which can be used to access the members. (The
conversions can be done implicitly; converting between void* and
another object pointer type doesn't require an explicit cast.)

But if you just want to pass a single char value to your start
routine, the cleanest way to do it is to pass a pointer to a char
object. Your start routine can then convert its void* argument to
char* and dereference it to obtain the original char value.
 
K

Keith Thompson

Juggernaut said:
Thanks for the thourough and absolutely great explanation.

Btw, I'll try to read the FAQ for this group before next time I post. :)


Btw, is there a FAQ I can read for this group?

Yes, it's at <http://www.eskimo.com/~scs/C-faq/top.html>. The
compressed text version at <ftp://ftp.eskimo.com/u/s/scs/C-faq/faq.gz>
is more up-to-date, but less convenient (don't ask me why the HTML
version hasn't been updated).

There's also a periodically posted welcome message that deals with the
newsgroup (the C FAQ deals mostly with the language). There are
several URLs with posting advice; I don't have them handy, but I'm
sure someone will post a followup.

Incidentally, one of the things emphasized in the welcome message is
that top-posting is considered poor style around here. Any new text
should follow (or be interspersed with) any quoted text, and quoted
text should be trimmed down to what's necessary for context.
 
J

Jason Curl

Juggernaut said:
I am trying to create a p_thread
pthread_create(&threads[k], &attr, Teste, (void *)var);
where var is a char variable.
But this doesnt't work, I get this message:
test.c:58: warning: cast to pointer from integer of different size.

The fact that it works with an integer is coincidence and is undefined
behaviour (probably the 'int' is physically the same size as a 'void *',
but it doesn't necessarily have to be). Actually, an 'int *' might be of
different representation/size to a 'char *'.

Typically (on say x86), sizeof(char)==1; sizeof(void *)==4. This is what
I think the compiler is complaining about.
Now I thought that when it was a void I could pass anything? Thing is it
works when I use an int, but in this case I wanted to use a char. It wouldnt
be hard to work around it, but it annoys me because I've heard anything can
be passed as long as its a void.

I have remembered to declare the function:
void *Teste(void *var)

and in the main method that created the thread I have declared the var
variable :
char var;
var = 'A'

and the function itself: void *Teste(void *var)

Now If I were to change the char declaration of var to f.example:
int var;
var = 1;

It works.

Now as I said I get this message:
test.c:58: warning: cast to pointer from integer of different size.

Why? And where does the pointer from integer come from? Theres no integer
involved, Im trying to pass a void thats a char.

If anyone can help me I would highly apriciate it.

I did a quick "google" and you might be interested in the page:

http://lists.svlug.org/pipermail/svlug/2000-June/027551.html

This is already some answers to your questions (and maybe some more)
 

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

Staff online

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top