Union type variable assignation --- in expression, in function argues

D

Denis Pithon

Hi, C lovers!

I stuck on an union problem

Here is snippet of my code

....

/* two pointers of function with repsectively one and two argues */
typedef int (*dce_sn_f)(dce_t*);
typedef int (*dce_io_f)(dce_t*, FILE*);



/* A union to store one of the previous declared type */
typedef union {
dce_sn_f sn; /* func with dce_t* argue */
dce_io_f io; /* func with dce_t* and FILE argues */
} dce_f;

....

typedef struct dce_slot_st {
dce_f f; /* may be dce_dn_t or dce_io_t */
const char *name;
} dce_slot_t;

....

static dce_slot_t *build_slot( dce_f fun, const char *name )
{
dce_slot_t *new_slot;



new_slot = utl_calloc( sizeof(dce_slot_t) );
if (new_slot) {
new_slot->f = fun; /* XXXXXX */
new_slot->name = name;



} else {
UTL_SYSERR( "cannot create new slot" );
return NULL;
}



return new_slot;

}

.....

dc->init = build_slot( stub_init, "stub_init" );


gcc detect an error on this last line and said:
" incompatible type for argument 1 of `build_slot' "

Does somedy show what is bad in my code

Does the expression (marked wih XXXXX in the code), look correct ? gcc
does not complain about it !

Thanks a lot

Denis
 
P

pete

Denis Pithon wrote:
dc->init = build_slot( stub_init, "stub_init" );

gcc detect an error on this last line and said:
" incompatible type for argument 1 of `build_slot' "

Does somedy show what is bad in my code

stub_init is undeclared.
 
D

Denis Pithon

pete said:
Denis Pithon wrote:




stub_init is undeclared.

Badly, stub_init is well declared ( just forget to copy it in the mail)

I obtain the same error with the simpler code below

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


typedef int (*f1_t)(int);
typedef int (*f2_t)(int, char*);


typedef union {
f1_t f1;
f2_t f2;
} f_t;


typedef struct {
f_t fun;
const char *name;
} f_slot_t;


int my_func(int a)
{
return a;
}


f_slot_t *do_work( f_t fun, const char *name )
{
f_slot_t *f = calloc( 1, sizeof(f_slot_t) );
f->fun = fun;
f->name = name;


return f;
}


int main()
{
f_slot_t *sl;


sl = do_work( my_func, "my_func" );
return 0;
}
 
D

Denis Pithon

pete said:
my_func isn't a union.
The first argument to do_work, should be a union.

I compile the code with
gcc -Wall -W -pedantic union.c

I just found that if remove -pedantic (eventually replace by -ansi), all
seems to be fine, if I cast my_func to (f_t) type, ie:

sl = do_work( (f_t) my_func, "my_func" );

compile quietly with: gcc -Wall -W -ansi union.c

If i keep -pedantic flag, gcc tell me that "ISO C forbids casts to union
type"...

So, I have to wrote as many do_work functions that I have type in the
union ???

Is there another way to it ?
 
V

Victor Nazarov

Denis said:
> pete wrote:
>

You must use something like:

sl = do_work(cast_from_f1_to_f (my_func), "my_func" );

where:

f_t cast_from_f1_to_f (f1_t f1)
{
f_t f;

return f.f1 = f1;
}

Another question is how you detect wich member of the union contain
correct data. In unions only one member contain correct data (there are
some exeptions, see standart), so you must store some additional info
about what member to use.

In your case you can use void * type instead of union.

typedef void *f_t

/* ... */

sl = do_work ((void *)my_func, "my_func");

Cast is needed there because standart doesn't allow explicit cast to
pointers to functions.
 
X

xarax

Denis Pithon said:
I compile the code with
gcc -Wall -W -pedantic union.c

I just found that if remove -pedantic (eventually replace by -ansi), all
seems to be fine, if I cast my_func to (f_t) type, ie:

sl = do_work( (f_t) my_func, "my_func" );

compile quietly with: gcc -Wall -W -ansi union.c

If i keep -pedantic flag, gcc tell me that "ISO C forbids casts to union
type"...

So, I have to wrote as many do_work functions that I have type in the
union ???

Is there another way to it ?

The problem is that you are trying to pass
the ADDRESS OF A FUNCTION as parameter that
expects a union aggregate.

You should change the function parameter to
accept a pointer to the union, rather than
the union itself. Then allocate the union
somewhere and stuff the function pointer
into that union. Then pass the address of
the union to your do_work function.

Turn the warnings back on. They are telling
you that you screwed up big time. Put in the
suggested fixes and turn on the warnings.


--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS!
Are ISV upgrade fees too high? Check our custom product development!
 
P

pete

Denis said:
Badly, stub_init is well declared ( just forget to copy it in the mail)

I obtain the same error with the simpler code below

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


typedef int (*f1_t)(int);
typedef int (*f2_t)(int, char*);


typedef union {
f1_t f1;
f2_t f2;
} f_t;


typedef struct {
f_t fun;
const char *name;
} f_slot_t;


int my_func(int a)
{
return a;
}


f_slot_t *do_work( f_t fun, const char *name )
{
f_slot_t *f = calloc( 1, sizeof(f_slot_t) );
f->fun = fun;
f->name = name;


return f;
}


int main()
{
f_slot_t *sl;


sl = do_work( my_func, "my_func" );
return 0;
}


I couldn't help but notice, that unions don't
seem to have anything to do with your posted code.
Your function doesn't make any use of a union type parameter,
and you don't have any unions available outside the function,
to pass as arguments. "fun" and "name", are structure members.
 
P

pete

Victor said:
You must use something like:

sl = do_work(cast_from_f1_to_f (my_func), "my_func" );

where:

f_t cast_from_f1_to_f (f1_t f1)
{
f_t f;

return f.f1 = f1;
}

Another question is how you detect wich member of the union contain
correct data. In unions only one member contain correct data (there are
some exeptions, see standart), so you must store some additional info
about what member to use.

In your case you can use void * type instead of union.

typedef void *f_t

/* ... */

sl = do_work ((void *)my_func, "my_func");

Cast is needed there because standart doesn't allow explicit cast to
pointers to functions.

I don't understand what you're saying.
You can't cast a function pointer to (void *),
therfore cast is not allowed there.
 
V

Victor Nazarov

pete said:
Victor Nazarov wrote:


I don't understand what you're saying.
You can't cast a function pointer to (void *),
therfore cast is not allowed there.

I've ment you need cast-operator in expression
p = (void *)my_func
where p was defined as void *;
I really don't know what standart says about this assignment, but that
has worked on my implementation so I could lately cast p back to pinter
to function. So I've just spread the idea of ALMOSTANYTYPE *
representation as void * to pointers to functions.
I want to know if that was a misstake. So I'm sorry if it was.
Sorry for my english.

Vir
 
P

pete

Victor said:
I've ment you need cast-operator in expression
p = (void *)my_func
where p was defined as void *;
I really don't know what standart says about this assignment, but that
has worked on my implementation so I could lately cast p back to pinter
to function. So I've just spread the idea of ALMOSTANYTYPE *
representation as void * to pointers to functions.
I want to know if that was a misstake.

Yes, it is a mistake. It is a nonstandard extension.
Pointers to functions,
can be converted to pointers to other types of functions,
but (void *), is a pointer to an incomplete object type,
and is incompatible with function pointers.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top