Implicit casting to union type? - c

Let's say we have the following parameters describing a person: name (string) and age (unsigned int). I want to write a universal setter API function that someone can call to set either the name or the age of a specific person. The reason for that will be explained later below.
What I did is define an enum type of person parameter names:
typedef enum person_param_name
{
NAME,
AGE,
} person_param_name_t;
And also a union type for person parameter values:
typedef union person_param_val
{
char* name;
unsigned int age;
} person_param_val_t;
Now, the function can look like this:
int set_person_param(person_param_name_t param_name, person_param_val_t param_val)
{
int ret = 0;
switch (param_name)
{
case NAME:
g_person_name = param_val.name;
break;
case AGE:
g_person_age = param_val.age;
break;
default:
ret = -1;
break;
}
return ret;
}
The problem with this approach is that one can't simply call the setter function like this (compiler throws warning):
set_person_param(NAME, "Alex");
set_person_param(AGE, 5);
But they have to explicitly cast the param value to person_param_val_t type, like this:
set_person_param(NAME, (person_param_val_t)"Alex");
set_person_param(AGE, (person_param_val_t )5);
The reason I want the universal setter function is because in the real program, I have a lot more parameters (close to 100) and I would need to write many (very similar) setter functions which would take a lot more lines of code.
Is there a better approach to this?

If you change the union so that the field names are identical to the enum constants:
typedef union person_param_val
{
char* NAME;
unsigned int AGE;
} person_param_val_t;
Then you can create a macro which will pass a properly initialized compound literal:
#define set_person_param_ext(k,v) \
set_person_param(k, (person_param_val_t){.k=v})
So then this:
set_person_param_ext(NAME, "Alex");
set_person_param_ext(AGE, 5);
Will expand to this:
set_person_param(NAME, (person_param_val_t){.NAME="Alex"});
set_person_param(AGE, (person_param_val_t){.AGE=5});

I could see:
typedef enum person_param_name {
NAME,
AGE,
} person_param_name_t;
typedef union person_param_val
{
char* name;
unsigned int age;
} person_param_val_t;
person_param_val_t person_param_val_init_charp(char *name) {
return (person_param_val_t){.name=name};
}
person_param_val_t person_param_val_init_u(unsigned age) {
return (person_param_val_t){.age=age};
}
#define MAKE_PERSON_PARAM_VAL(x) _Generic((x) \
, unsigned: person_param_val_init_u \
, char *:person_param_val_init_charp \
)(x)
int set_person_param(person_param_name_t param_name, person_param_val_t param_val);
#define set_person_param(a, b) \
set_person_param(a, MAKE_PERSON_PARAM_VAL(b))
int main() {
set_person_param(NAME, "Alex");
set_person_param(AGE, 5u);
}
With GCC with extension, you will get away with just:
#define set_person_param(a, b) \
set_person_param(a, (person_param_val_t)(b))
But I would not write such code. This is C. In C, you would write it all explicitly. I do not see a value in person_param_name. You still have to enumerate all types explicitly inside set_person_param. I would just write set_person_param_age(unsigned age) and set_person_param_name(char *name) explicitly. If not, I would consider rethinking the whole approach, as most probably you want to implement virtual function. I would advise, strongly consider not writing an interface with endless number of cases in enums, because you might end up with this. Instead, create objects with a pointer to the interface stored with a vtable.

You do not need any magic. This macro is enough
#define set_person_param(param, val) g_person_##param.param = (val)
And this sample function:
int foo(void)
{
person_param_val_t g_person_name, g_person_age;
set_person_param(name, "Alex");
set_person_param(age, 5);
}
will be preprocessed to:
int foo(void)
{
person_param_val_t g_person_name, g_person_age;
g_person_name.name = "Alex";
g_person_age.age = 5;
}
As I understand it was something you wanted to archive. Your enum type is not needed.
If you want val to be the same union type then:
#define set_person_param(param, val) g_person_##param = (val)
example:
set_person_param(name, (person_param_val_t){.name="Alex"});

Related

Can you allow one of a few types of pointers as an argument without void*?

In plain c, I have a situation where I would like to allow a function to accept multiple types of pointers. To illustrate my situation, here could be one use case:
void myfunction([int* or char*] value) {
*value = 0xdd; // safe since value is at least as big as a char*
}
And here is another:
#define MAGIC 0xabcdef0
typedef struct {
int magic;
char* content;
} MyStruct;
void myfunction([int* or MyStruct*] value) {
if (*value != MAGIC) {
printf("Got an int\n");
} else {
printf("Got a MyStruct\n");
}
}
// example:
int input1 = 0;
MyStruct input2 = { MAGIC, "hello world" };
myfunction(input1); // "Got an int"
myfunction(input2); // "Got a MyStruct"
Both of these situations could be made possible with a void* parameter type, but that would in effect allow any type of pointer to be passed in without a compile error. Is there a way to restrict the function to accept only a specific subset of pointer types?
If you can use features that are new in C11, the _Generic keyword can solve your problem:
void myfunction(void *value) {
// ...
}
#define myfunction(x) myfunction( \
_Generic((x), char *: (x), int *: (x)) )
As Houman pointed out, you can use a union to do the job, however, you still have the problem that you must identify the type that is set in the union type. You can solve that using an enum to identify the type inside your function.
union myUnion {
int* intPointer,
MyStruct* myStructPointer
};
enum typeEnum {
INT,
MYSTRUCT
};
void myfunction(union myUnion union, enum typeEnum type) {
if (type == INT)
// you got an integer
else if (type == MYSTRUCT)
// you got a struct
// You can add future additions here
}
You could do this:
void myfunction(void *s)
{
if ( *(int *)s == MAGIC )
{
MyStruct *p = s;
printf("%s\n", p->content);
}
}
However this design makes it easy to write buggy code that the compiler will not catch for you, so I would recommend coming up with a slightly different design (e.g. tagged unions).
No, use void* and then cast.
One could think that I can use a void* and then check about the casting inside the function, and if not the expected type, raise an error, but no, you cannot do that either, since void* loses all its type information.
Damn I am writing just before going into the shower. I couldn't resist! BRB :) -- OK, turns out R..'s answer from the future is the correct one! ;)

Single handler to set values of varying types

I have a bunch of global variables which are set through callback. I get notification for one of them at a time. I want to keep single function to update this state. This is version of how I am doing.
typedef struct {
int g_var_a;
char g_var_b;
double g_var_c;
long g_var_d;
} global_state_t;
typedef union {
int g_var_a;
char g_var_b;
double g_var_c;
long g_var_d;
} global_change_t;
typedef enum {
VAR_A;
VAR_B;
VAR_C;
VAR_D;
} global_change_type_t;
global_state_t gs = {0};
void udpate_global_state(global_change_t *c, global_change_type_t type) {
switch (type) {
case VAR_A: {
gs.g_val_a = c->g_var_a;
break;
}
...
....
}
}
This is called as:
callback() {
...
global_change_t c = {.g_var_a = 1234};
update_global_state(&c, VAR_A);
}
But to me this looks bad. There are three construct: struct, union, enum all of which have to be in sync. Isn't there a better way to do this ?
First I'll note that you can decrease maintenance risk by making your union with only one field per struct field type, not one field per field. You can also do tricks with macros to eliminate redundancies entirely. I can explain this further if you're interested.
You can also abstract away from the data with functions. Unfortunately to give them all the same signature you need either a union as you used or void pointers. I'll try the latter.
typedef struct {
int g_var_a;
char g_var_b;
double g_var_c;
long g_var_d;
} GLOBAL_STATE;
GLOBAL_STATE gs[1];
typedef void (*UPDATER)(void*);
void a_updater(void *val) { gs->g_var_a = *(int*)val; }
void b_updater(void *val) { gs->g_var_b = *(char*)val; }
void c_updater(void *val) { gs->g_var_c = *(double*)val; }
void d_updater(void *val) { gs->g_var_d = *(long*)val; }
void udpate_global_state(UPDATER updater, void *val) {
updater(val);
}
NB You should not used types ending in _t as these are reserved for system headers by the C Standard.
Now you can say
{
int i[1] = { 3 };
char c[1] = { 'a' };
double d[1] = { 1.234 };
long g[1] = { 123456 };
update_global_state(a_updater, i);
update_global_state(b_updater, c);
update_global_state(c_updater, d);
update_global_state(d_updater, g);
}
The 1-element array trick is purely esthetic. Drop it and use & in the update calls if you like. Both ways produce the same code.
Of course this is not type safe, but neither is your solution. It does reduce code structures that must be maintained in synch.
There's no elegant way to define run-time variants in C.
The 2 approaches include:
struct containing a union with actual value and some mechanism to dispatch based on actual type. In simple case this can be an enum tag, in more complicated cases there will be some function pointers storing references to the value_is() and get_value_as() methods (this later approach is mostly used in dynamic language interpreters).
Universal value type (most often a string) which can encode distinct variant values. The receiving function will then do some simple parsing to get the data out (this is essentially equivalent to struct with union and enum tag), but may result in more maintainable and readable programs at an expense of some (not that big) performance loss.

How to know the Data type of a variable of unknown type in C?

#include<stdio.h>
void fun(void *x)
{
//what is the data type of 'x', since I could have passed float instead of
// int so first I have to check datatype of this and then proceed further.
}
int main()
{
int n=10;
fun(&n);
}
You can see that we dont know the type of 'x' in function fun() so how could we find out that without using(passing) any other information in function argument?
C11 has type-generic expressions to help you solve this problem. You could do something like this example:
#define myFunction(X) _Generic((X), \
    int *: myFunctionInt, \
    float *: myFunctionFloat, \
    default: myFunctionInt \
    )(X)
void myFunctionInt(int *x);
void myFunctionFloat(float *x);
And then call it the way you are:
int n = 10;
myFunction(&n);
or:
float n = 10.0f;
myFunction(&n);
You will need to implement the separate target functions, but you could just do the pointer magic there and pass off to a common handler, for example.
C does not have runtime type information. When you pass a pointer, then you pass a naked pointer - a memory address.
If you are using pointers to void but need to know the type, then you have to pass some additional information. Otherwise, you create different functions for different types, like foo that expects an int, dfoo that expects a double and so on.
You cannot know the type when you cast to a void *. You have to be careful while using a void pointer, because you can cast it to any type. That is the purpose to have a void pointer.
C does not allow to get the type of the variable passed by void*. The only thing, that you can do it is write kind of object oriented code by your self.
Probably something like this:
typedef struct generic_type_s
{
void* data;
void (*f)(void* data);
} generic_type_t;
void f_int(void* _data)
{
int* data = (int*)_data;
// Do something
}
int main()
{
int data1 = 10;
// Generic variable initialization
generic_type_t gv;
gv.data = &data1;
gv.f = f_int;
// Calling an appropriate function
gv.f(gv.data);
return 0;
}
The C way of doing this is using a tagged union:
typedef enum {
// will default to TypeUnitialized if unspecified in structure initializer
TypeUninitialized = 0,
TypeFloat = 1,
TypeInt
} type_t;
typedef struct {
type_t type;
union {
int u_int;
float u_float;
};
} gen_val_t;
void fun(gen_val_t v)
{
switch (v.type) {
case TypeFloat:
// process float
break;
case TypeInt:
// process int
break;
default:
// error
break;
}
}
int main(int argc, char **argv)
{
gen_val_t ov = { .type = TypeFloat,
.u_float = 3.45 };
fun(ov);
}

Accessing structure members without using dot operator

I don't even know, whether what I'm asking is something stupid or not. I am not asking you to write any code for me, but an idea to do something in a better way.
I have a struct with a large number of items like this:
typedef struct _myStruct
{
int int1;
char char1;
int int2;
:
:
int int50;
}myStruct;
I have another enumeration which has a single entry for each item in myStruct.
enum
{
eINT1,
eCHAR1,
eINT2,
:
:
eINT50
} PARAMETER_ID;
I want to write a function for each data type [say one for int, one for char, one for string etc], which return the value of a member of myStruct, when the PARAMETER_ID is given as input.
For example I need a int GetInt(PARAMETER_ID) function which return the value of int1 when eINT1 is passed as an argument. Similarly I am going to have char GetCharacter(PARAMETER_ID), float GetFloat(PARAMETER_ID) etc.
The number of items in the struct can be large. So using a switch-case for each item will not be a viable option.
Only other option I can think of is using the address of the structure variable and offsetof() function to calculate the address of the parameter and then by memcpying the required bytes into a variable. In that case I need to keep the offset of each parameter somewhere, but that is not a problem.
I am looking for alternate options to do this. Any help will be greatly appreciated.
Thank you.
A large switch is a good viable option.
You might also play preprocessor tricks.
You could have a mystruct.def file containing
INTFIELD(int1)
CHARFIELD(char1)
INTFIELD(int2)
etc... Then you would include it several times; to declare the structure:
struct _myStruct {
#define INTFIELD(F) int F;
#define CHARFIELD(F) char F;
#include "mystruct.def"
#undef INTFIELD
#undef CHARFIELD
};
To declare the enumeration (using e_int1 instead of eINT1)
enum field_en {
#define INTFIELD(F) e_##F,
#define CHARFIELD(F) e_##F,
#include "mystruct.def"
#undef INTFIELD
#undef CHARFIELD
};
To implement the accessor,
int get_int(struct _myStruct*s, enum field_en f)
{
switch (f) {
#define INTFIELD(F) case e_##F: return s->F;
#define CHARFIELD(F) /*nothing*/
#include "mystruct.def"
#undef INTFIELD
#undef CHARFIELD
default: return 0;
}}
I don't claim this is better or more readable code, but that kind of programming style does appear in some C or C++ programs (e.g. GCC internals with its gcc/tree.def)
If you code is a very large code base, and you are ready to spend days of work (e.g. because you have a lot of such struct and don't want to play such tricks) you might consider making a GCC extension with MELT (a high-level domain specific language to extend GCC) to help you; you probably can make a MELT extension to generate the accessor functions for you.
You could also convince your boss to generate both the struct, the enum and the accessor functions from an ad-hoc descriptive file (using awk, python or whatever). GCC does such tricks for its options file, e.g. gcc/common.opt
At last, if the header containing the _myStruct is so sacred that you are not allowed to touch it, and if it is very cleanly formatted, you might make an ad-hoc (e.g. awk) script to get that declaration and process it.
NB a good compiler optimizes dense switch statements as indexed jumps which take constant time, even for hundred of cases.
#include <stddef.h>
#include <stdio.h>
struct S
{
int int1;
char char1;
int int2;
char char2;
long long1;
} myStruct = {12345, 'A', 321, 'B', -1L};
enum
{
eINT1 = offsetof(struct S, int1),
eCHAR1 = offsetof(struct S, char1),
eINT2 = offsetof(struct S, int2),
eCHAR2 = offsetof(struct S, char2),
eLONG1 = offsetof(struct S, long1),
} PARAMETER_ID;
char GetChar(int para_id)
{
return *((char*)((char *)&myStruct + para_id));
}
int GetInt(int para_id)
{
return *((int*)((char *)&myStruct + para_id));
}
long GetLong(int para_id)
{
return *((long*)((char *)&myStruct + para_id));
}
void main(void)
{
printf("offsetof int1 = %d\n", eINT1);
printf("offsetof char1 = %d\n", eCHAR1);
printf("offsetof int2 = %d\n", eINT2);
printf("offsetof char2 = %d\n", eCHAR2);
printf("offsetof long1 = %d\n", eLONG1);
printf("int1 = %d\n", GetInt (eINT1));
printf("char1 = %c\n", GetChar(eCHAR1));
printf("int2 = %d\n", GetInt (eINT2));
printf("char2 = %c\n", GetChar(eCHAR2));
printf("long1 = %ld\n", GetLong(eLONG1));
}
You partially answer your own question, offsetof is meant to be used for this very purpose. You have to consider struct padding/alignment. I think you are looking for something similar to this:
#include <stddef.h> // size_t, offsetof
#include <string.h> // memcpy
#include <stdio.h>
typedef struct
{
int int1;
char char1;
int int2;
int int50;
} myStruct;
typedef enum
{
eINT1,
eCHAR1,
eINT2,
eINT50,
ITEMS_IN_STRUCT
} myEnum;
static const size_t MYSTRUCT_MEMBER_OFFSET [ITEMS_IN_STRUCT] =
{
offsetof(myStruct, int1),
offsetof(myStruct, char1),
offsetof(myStruct, int2),
offsetof(myStruct, int50),
};
static const myStruct MS;
static const size_t MYSTRUCT_MEMBER_SIZE [ITEMS_IN_STRUCT] =
{
sizeof(MS.int1),
sizeof(MS.char1),
sizeof(MS.int2),
sizeof(MS.int50)
};
void myStruct_get_member (void* result, const myStruct* ms, myEnum id)
{
memcpy (result,
(char*)ms + MYSTRUCT_MEMBER_OFFSET[id],
MYSTRUCT_MEMBER_SIZE[id]);
}

Is there any way to pass a structure type to a c function

I have some code with multiple functions very similar to each other to look up an item in a list based on the contents of one field in a structure. The only difference between the functions is the type of the structure that the look up is occurring in. If I could pass in the type, I could remove all the code duplication.
I also noticed that there is some mutex locking happening in these functions as well, so I think I might leave them alone...
If you ensure that the field is placed in the same place in each such structure, you can simply cast a pointer to get at the field. This technique is used in lots of low level system libraries e.g. BSD sockets.
struct person {
int index;
};
struct clown {
int index;
char *hat;
};
/* we're not going to define a firetruck here */
struct firetruck;
struct fireman {
int index;
struct firetruck *truck;
};
int getindexof(struct person *who)
{
return who->index;
}
int main(int argc, char *argv[])
{
struct fireman sam;
/* somehow sam gets initialised */
sam.index = 5;
int index = getindexof((struct person *) &sam);
printf("Sam's index is %d\n", index);
return 0;
}
You lose type safety by doing this, but it's a valuable technique.
[ I have now actually tested the above code and fixed the various minor errors. It's much easier when you have a compiler. ]
Since structures are nothing more than predefined blocks of memory, you can do this. You could pass a void * to the structure, and an integer or something to define the type.
From there, the safest thing to do would be to recast the void * into a pointer of the appropriate type before accessing the data.
You'll need to be very, very careful, as you lose type-safety when you cast to a void * and you can likely end up with a difficult to debug runtime error when doing something like this.
I think you should look at the C standard functions qsort() and bsearch() for inspiration. These are general purpose code to sort arrays and to search for data in a pre-sorted array. They work on any type of data structure - but you pass them a pointer to a helper function that does the comparisons. The helper function knows the details of the structure, and therefore does the comparison correctly.
In fact, since you are wanting to do searches, it may be that all you need is bsearch(), though if you are building the data structures on the fly, you may decide you need a different structure than a sorted list. (You can use sorted lists -- it just tends to slow things down compared with, say, a heap. However, you'd need a general heap_search() function, and a heap_insert() function, to do the job properly, and such functions are not standardized in C. Searching the web shows such functions exist - not by that name; just do not try "c heap search" since it is assumed you meant "cheap search" and you get tons of junk!)
If the ID field you test is part of a common initial sequence of fields shared by all the structs, then using a union guarantees that the access will work:
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int id;
long junk2;
} Bar;
typedef union
{
struct
{
int id;
} common;
Foo foo;
Bar bar;
} U;
int matches(const U *candidate, int wanted)
{
return candidate->common.id == wanted;
}
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 42, 0 };
U fu;
U bu;
fu.foo = f;
bu.bar = b;
puts(matches(&fu, 23) ? "true" : "false");
puts(matches(&bu, 42) ? "true" : "false");
return 0;
}
If you're unlucky, and the field appears at different offsets in the various structs, you can add an offset parameter to your function. Then, offsetof and a wrapper macro simulate what the OP asked for - passing the type of struct at the call site:
#include <stddef.h>
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int junk2;
int id;
} Bar;
int matches(const void* candidate, size_t idOffset, int wanted)
{
return *(int*)((const unsigned char*)candidate + idOffset) == wanted;
}
#define MATCHES(type, candidate, wanted) matches(candidate, offsetof(type, id), wanted)
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 0, 42 };
puts(MATCHES(Foo, &f, 23) ? "true" : "false");
puts(MATCHES(Bar, &b, 42) ? "true" : "false");
return 0;
}
One way to do this is to have a type field as the first byte of the structure. Your receiving function looks at this byte and then casts the pointer to the correct type based on what it discovers. Another approach is to pass the type information as a separate parameter to each function that needs it.
You can do this with a parameterized macro but most coding policies will frown on that.
#include
#define getfield(s, name) ((s).name)
typedef struct{
int x;
}Bob;
typedef struct{
int y;
}Fred;
int main(int argc, char**argv){
Bob b;
b.x=6;
Fred f;
f.y=7;
printf("%d, %d\n", getfield(b, x), getfield(f, y));
}
Short answer: no. You can, however, create your own method for doing so, i.e. providing a specification for how to create such a struct. However, it's generally not necessary and is not worth the effort; just pass by reference. (callFuncWithInputThenOutput(input, &struct.output);)
I'm a little rusty on c, but try using a void* pointer as the variable type in the function parameter. Then pass the address of the structure to the function, and then use it he way that you would.
void foo(void* obj);
void main()
{
struct bla obj;
...
foo(&obj);
...
}
void foo(void* obj)
{
printf(obj -> x, "%s")
}

Resources