I have a problem with typedef union as parameter for a function-call.
definition of the typedef
union uParameter { byte bByte; // 8 bit unsigned int16 iInt16; // 16 bit signed int32 iInt32; // 32 bit signed }; typedef union uParameter USR_tu_Para;
prototype of a function that uses this typedef
void SetSomething(USR_tu_Para para);
The question is: how can I call the SetSomething-function with a constant parameter.
SetSomething(100);
This call creates a compiler error: #167: argument of type "int" is incompatible with parameter of type "USR_tu_Para"
I tried to cast the parameter witch (USR_tu_Para) or (USR_tu_Para.iInt16). But the compiler denied everything I tried.
Any ideas?
Why a union here? The parameter will occupy a full register in any case.
See here how to use transparent unions at the expense of limited portability: infocenter.arm.com/.../armccref_cacifaid.htm
why a union: i agree at this example there is no need to use a union. But in my application it is a little bit more complicated. I use a pointer to access different functions. These functions imlicitely know if they need 8, 16 or 32 bits. I also misapplied that there are signed datatypes in the union too.
The use of unions at this point simplifies the software a lot.
I did not rumble through the benefit of transparent unions. But the crux of the matter will be that the software has to run under Visual C++ too. I don't think transparent unions will be supported there.
Just remember that the stricter data type checking you can use, the quicker you - or the next developer who may pick up this project - will catch goofs in the code.
With a union that doesn't have a field to say what type of info it contains, together with functions that "automatically" know what union member to pick up, you have completely nuked the compilers ability to track used data types. You could just as well switch to ugly typecasted pointers - yes, very ugly but at least a code reader would know he/she is in very, very dangerous terrain.
Does it?
Wouldn't void* do it?
But I think both give huge risks of problems due to data (mis)alignment...
Sounds like all the more reason not to be using any "cunning tricks" like this at all!
For portability, you want to stick to making things as "straightforward" as possible - messing with unions and/or void* pointers sounds like a great way to run into all sorts of implementation-dependant traps...
Does VC++ support C99? Try this
SetSomething((USR_tu_Para) {0});
-- Marcus
Hi Per, thanks for your reply. My first idea was to use void pointers. But finally I decided to reduce the risk a little bit.
I placed enough warnings in my code, that this corner should not be touched without switching on the brain before.
This is the definition of my pointer-array
void (*azfSet[IOACC_ATT_ANZ][5])(word, USR_tu_Parameter)
I hope this scares enough :-)
Anyway: it should be possible to pass a numeric value to a function with union as parameter (standard in c++ without any use of unions).
You could use conversion functions like int2union() and hope that the compiler inlines them...
The union as defined above would be guaranteed to be word aligned. I am not recommending the use of unions here, but we want to get the facts straight.
-- Marcus http://www.doulos.com/arm/
I already tried this. But not even KEIL gets well anlong with it. :-(
error: #119: cast to type "USR_tu_Para" is not allowed
int2union(); it looks like I do not have too much other possibility except of not using unions or your solution.
"hope the compliler inlines" Hope is the last to die ;-)
--c99
Marcus
But finally I decided to reduce the risk a little bit.
But you didn't. That union is exactly as risky as passing stuff via (void *). Heck, even variable-number-of-arguments functions would be (slightly) safer than that!
Oh, and the only reason for anyone to be scared of a declaration an array of function pointers like this:
is that you decided against doing it in a much less confusing way, e.g.
#define MEANINGFUL_NAME 5 typedef void (*azfFunction_t)(word, USR_tu_Parameter); azfFunction_t azfSet[IOACC_ATT_ANZ][MEANINGFUL_NAME]
--99 with this pragma it is in fact possible to cast a constant with (USR_tu_Para). But as expected Visual C++ does not support C99.