-Wincompatible-pointer-types and enum - c

Implicit cast from short* to int* prints the warning about incompatible pointer type (and I understand why).
Implicit cast from enum* to int* prints same warnig.
There's a tool snacc that generates the following code:
typedef enum
{
CHARGINGCALLING = 0,
CHARGINGCALLED = 1,
NONECHARGING = 2
} ChargedParty; /* ENUMERATED { CHARGINGCALLING (0), CHARGINGCALLED (1), NONECHARGING (2) } */
typedef struct MSOriginatingSMSinSMS_IWMSC /* SET */
{
ChargedParty* chargedParty; /* [6] IMPLICIT ChargedParty OPTIONAL */
} MSOriginatingSMSinSMS_IWMSC;
#define BEncChargedPartyContent BEncAsnEnumContent
int BEncMSOriginatingSMSinSMS_IWMSCContent (BUF_TYPE b, MSOriginatingSMSinSMS_IWMSC *v) {
BEncChargedPartyContent (b, (v->chargedParty));
...
}
A header file shipped with this tool:
int BEncAsnIntContent (BUF_TYPE b, int *data);
#define BEncAsnEnumContent BEncAsnIntContent
The call to BEncChargedPartyContent prints the warning.
Can I modify the declaration of BEncAsnEnumContent so it accepts without a warning pointers to any enum, but not void* or short*?
Of course using sed I could replace the macro BEncChargedPartyContent with a static function:
static AsnLen BEncChargedPartyContent (BUF_TYPE b, ChargedParty *data)
{
return BEncAsnEnumContent(b, (int*)data);
}
But there're too many of them.

Your own proposal with a static function sounds not so bad.
Can I modify the declaration of BEncAsnEnumContent so it
accepts without a warning pointers to any enum, but not
void* or short*?
If you want, you can use a static assertion as John Zwinck hinted at.
#define BEncAsnEnumContent(b, d) ({\
_Static_assert(sizeof(int) == sizeof *(d), "wrong data size");\
BEncAsnIntContent(b, (int *)d); })
What you think of in your comment below is a viable alternative with the advantage that it allows enumerations of different sizes; this is how I understand what you mean:
#define BEncAsnEnumContent(b, d) MyEncAsnEnumContent(b, *(d))
static int MyEncAsnEnumContent(BUF_TYPE b, int val)
{
return BEncAsnIntContent(b, &val);
}

The enumeration constants, that is the list of values in your enum declaration, are guaranteed to be of type int. However, this does not apply to the enum variable itself. An enum need not be compatible with int nor with another, different enum type variable. The size can vary from case to case and from compiler to compiler.
This is the root of the problem. If you mix enum and int, or two different enums with each other, all is fine if they have the same size. They are then compatible and you can convert pointers from one of the types to the other without problems.
However, if they are not of the same size, you cannot do this. It would give incompatible types: you would violate the strict aliasing rule and there might also be alignment issues. Plus the obvious: if you try to read a large chunk of data from a location where only a small chunk of data is stored, there's no telling what you will end up with.
The reliable solution is to change your function to simply use an integer type instead of a pointer:
int BEncAsnIntContent (BUF_TYPE b, int data);
There doesn't seem to be a reason why they pass the parameter through a pointer in the first place. Keep it simple.

Related

Declaring void pointers to push type handling downstream

Is it ever common to do something like the following:
void *x = (void *) "one";
void *y = (void *) 2;
void *z = (void *) NULL;
Instead of:
char * x = "one";
int y = 2;
My reason for asking this is the ability to call a function that can accept multiple types. For example, a concat of various elements like is available in javascript. It seems like in a way using (void *) is just a simple way to mean "any type".
No, because you can't dereference a void pointer: you have to know what type is being stored, rendering the idea useless.
What you might be looking for is a variant type.
enum type {
CHAR, INT, DOUBLE, STR
};
typedef struct {
union {
char c;
int i;
double d;
char *str;
};
enum type t;
} variant;
void displayGenericObjec(variant v)
{
switch (v.t) {
case CHAR:
putchar(v.c);
break;
case INT:
printf("%d", v.i);
break;
case DOUBLE:
printf("%f", v.d);
break;
case STR:
printf("%s", v.str);
break;
}
}
variant x;
x.t = INT;
x.i = 42;
displayGenericObject(x);
This isn't a very practical solution, but it works for trivial code that only needs a few types.
Usually, it is not a good idea to write functions that take any argument. As noted in the comments, you lose on the compiler provided type-checking.
However, there are some cases where you might want to consider this using 'void *', which are (usually) considered acceptable are: (1) varargs functions and (2) callback. Important to emphasize that it is better to consider alternative implementation, if possible.
varargs functions are functions like 'printf', 'scanf', etc, where the function can accept variable number of arguments, potentially of different types, and will usually use clues (or convention) from the first arguments to properly decode the remaining arguments.
Callback are other example, where the code will sometimes have to specify a function that will be called on event. Many frameworks will require the callback to match a predefined "typedef", where the code will later cast the arguments into the actual type. For example, the 'qsort' prototype require a 'compar' function, which is generically defined to take 'void *', where the actual function will cast the parameters to the actual type.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
On historical note, the initial versions of "C" (sometimes call "K&R C") did allow functions to be defined without formal parameter list. Practical experience has proven this to be risky, non-productive. In those days, you could write function in header files like:
/* in file.h */
int foo() ;
/* in file.c */
int foo(a)
int a ;
{
}
/* in prog.c */
{
a(5,4,"x") ;
}

C generic Parameter into Function pointer

Is it possible in C(not C++) to have a fuction pointer that takes a generic value(not a pointer), with -pedantic and -wall -werror flags set.
Note: I can't change the parameter Type. The code has to support uint8_t, uint16_t, etc... types as the parameters
Goal: to solve the problem with code.
Question
Is there a way to typecast a uint8_t(and/or uint16_t) parameter to a void*(Approach1)?
specifically to pass a non-pointer type value to a void* value.
Is there a way to setup a Generic Type that will work with all the different values(Approach 2)?
Last resort
Is there a way to set a specific compiler Exception in the code?(this question has been answer)
Approach 1(causes a invalid conversion from uint8_t to void*)
typedef struct
{
void (*set_func)(void*);
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
uint8_t a = 123;
uint16_t b = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue to appease compiler warning
pointerFunction.set_func = (void(*)(void*))&setValue;
pointerFuncionShort.set_func = (void(*)(void*))&setShortValue;
//use the function pointer with non-pointer parameter
// Compile ERROR thrown invalid conversion from uint8_t to void*
pointerFunction.set_func(a);
pointerFuncionShort.set_func(b);
}
Aprroach 2(causes a Too Many Parameters Compile Error)
typedef struct
{
void (*set_func)();//Blank parameter to allow multiple args
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
uint8_t a = 123;
uint16_t b = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue to appease compiler warning
pointerFunction.set_func = (void(*)())&setValue;
pointerFuncionShort.set_func = (void(*)())&setShortValue;
//use the function pointer with non-pointer parameter
pointerFunction.set_func(a);// Compile ERROR thrown "Too many Args"
pointerFuncionShort.set_func(b);// Compile ERROR thrown "Too many Args"
}
UPDATE
To add clarity to the problem.
I have 100's of functions with 1 parameter.
The 1 parameter of the functions are different types.
I can't change any of the functions, but I want to have 1 function pointer type(or more based on type) to any of the functions.
I can change any of the types associated with the function pointer and the type to the function pointer, but not what it is pointing too.
No, it is not.
Simple answer: The called function does not know how to even fetch the argument.
Details: The function code is already fixed when it is called (executed). So it contains code to access the argument, which depends on the type of the arguemtn (e.g. for an uint32_t, a 32 bit load/soter is required, for an uint8_t an 8 bit load/store). So it cannot handle even the value fetch properly.
Different from C++ and higher languages like Python, C does not have a concept of run-time type identification built-in.
However, you can pass a union to the function and handle each variant in the function seperately. That would generate all possible accesses. However, you have to specify which actual type is being passed. This is normally done by a second argument which specifies the actual type.
That union could also be a struct composed of the type-identifier and the actual value. But that is just an envelope, everything is still explicit.
typedef union {
int i;
float f;
} MyValue;
typedef enum {
MY_VALUE_int,
MY_VALUE_float
} MyValueType;
void func(MyValueType type, MyValue value)
{
switch ( type ) {
...
}
}
int main(void)
{
func(MY_VALUE_int, (MyValueType){ .i=1 });
}
The compound literal argument only works for constants, otherwise you have to assign the value to a union first (or just use that union).
gcc has an extension to avoid this, so you can have a function which takes such a union, but the caller may use a simple cast, instead of a compound literal. That works for variables, too:
func(MY_VALUE_float, (MyValueType)1.0);
An alternative would be passing a const void * and internally casting. However, that is even more risky than the union approach.
All approaches require pasing the actual type explicitly (e.g. using an enum).
C11 allows to create a macro which evaluates different expressions, according to the type of an argument using the new _Generic construct. With that the original approach can be simulated (using gcc extension, normal way is possible, but more complicated):
// use the code of the first block here
#define func_generic(val) _Generic((val), \
int : func(MY_VALUE_int, (MyValueType)(val)), \
int : func(MY_VALUE_int, (MyValueType)(val)) )
// and call like:
func_generic(1);
func_generic(1.0);
However, note the restriction of _Generic: No two compatible types are allowed for the type-selector (i.e. const int and int are not allowed both) for uint16_t and uint32_t this works, however.
Note that gcc (you apparently use) supports C11 using -std=c11 or std=gnu11. The latter also enables GNU-extensions.
The short answer is no.
You have several problems:
1) The different functions all have to have the same signature to allow the function pointer to point to them.
2) The functions are taking their args by value which means a copy will be passed in and any actions you take on the value will not appear to have any affect outside the function call. Since you don't allow pointers I cant see any way round this.
If you are not bothered about problem 2 then you could try declaring a variadic function which will accept args of any type.
e.g.
void doSomethingWithValue(enum MyType type ...)
{
va_list args;
va_start( args, type);
switch( type)
{
case Uint8Type:
{
uint8_t value = va_arg(args, uint8_t);
//doSomething to value
}
break;
.
.
.
}
va_end(args);
}
Where MyType is an enum set up to identify which type is passed in.
which is used like so:
uint8_t value = 7;
doSomethingWithValue(Uint8Type, value);
//note that value is still 7
Note that both of your exampels exibit Undefined Behaviour because you call a function through a pointer of another (function) type.
I found a solution that relies on the fact that there are a limited number of function types known in advance. I think however that it is too much hassle. Just call the original function.
enum GFType {
GF_UINT8,
GF_UINT16 // etc
};
struct GenericFunction {
void (*func)(void);
GFType type;
};
void callGenericFunction(GenericFunction func, uint64_t p) // largest type
{
switch (func.type) {
case GF_UINT8:
((void (*)(uint8_t))func.func)(p);
return;
case GF_UINT16:
((void (*)(uint16_t))func.func)(p);
return;
default:
assert(1); // unimplemented function type
}
}
void setValue(uint8_t byteValue) // Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue) // Not a pointer parameter
{
byteValue++;
}
int main() {
uint8_t a = 123;
uint16_t b = 321;
GenericFunction pointerFunction;
GenericFunction pointerFunctionShort;
pointerFunction.func = (void (*)(void))setValue;
pointerFunction.type = GF_UINT8;
pointerFunctionShort.func = (void (*)(void))setShortValue;
pointerFunction.type = GF_UINT16;
callGenericFunction(pointerFunction, a);
callGenericFunction(pointerFunctionShort, b);
return 1;
}
Note that
a function-pointer may be freely converted to any other
function-pointer type and back again, and you will get the original
pointer.
This is what we use. We can't even use void * (because it is a data pointer, not a function pointer) to store the function pointer. So I used void (*)(void) to store the function pointer. An enum tells us to what kind of function we must convert it when we need to cal it.
If you can use C11, there is a way to do this using _Generic:
#include <stdio.h>
#include <inttypes.h>
#define setvalue_generic(x) _Generic((x), \
uint8_t: setValue, \
uint16_t: setShortValue \
)(x)
void setValue(uint8_t byteValue)
{
printf("setValue: %" PRIu8 "\n", byteValue);
byteValue++;
}
void setShortValue(uint16_t byteValue)
{
printf("setValue: %" PRIu16 "\n", byteValue);
byteValue++;
}
int main(void)
{
uint8_t a = 123;
uint16_t b = 321;
setvalue_generic(a);
setvalue_generic(b);
return 0;
}
Seems to work well with gcc -std=c11 -pedantic -Wextra -Wall.
#bolov answer is good for handling the different types, this is just a different way of handling the same issue, but with 1 parameter.
The downside to this approach is that the type in main has to be GENERAL_TYPE. In my application I can change the type of the parameter, but I can change the type of the functions that I'm pointing to.
the (void(*)(GENERAL_TYPE))& handles the function's parameter types, and the Union handles the types of all the different sizes.
Another option is to have function pointers for each type too.
typedef union generalType
{
uint8_t byteData;
uint16_t shortData;
uint32_t intData;
int integerData;
uint64_t longData;
void * voidData;
//Add any type
} GENERAL_TYPE;
typedef struct
{
void (*set_func)(GENERAL_TYPE);
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
GENERAL_TYPE a.byteData = 123;//restricted to use GENERAL_TYPE here
GENERAL_TYPE b.shortData = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue parameter to be a general type will
//Allow it to send the data of whatever type.
pointerFunction.set_func = (void(*)(GENERAL_TYPE))&setValue;
pointerFuncionShort.set_func = (void(*)(GENERAL_TYPE))&setShortValue;
//use the function pointer with non-pointer parameter
pointerFunction.set_func(a);
pointerFuncionShort.set_func(b);
}

Casting Structs With Void Pointers into Structs With Typed Pointers

Short version:
Suppose I have two structs:
struct charPtrWithLen
{
size_t len;
char * charPtr;
}
struct voidPtrWithLen
{
size_t len;
void * voidPtr;
}
Is there a way to cast voidPtrWithLen into charPtrWithLen and vice-versa, or even better, implicitly convert one into the other, much the same way that a char * and a void * can be readily cast and implicitly converted between each other?
Put another way:
I am trying to write all my C so that all pointers to arrays bring their size information with them. I am also trying to write generic functions using void pointers where applicable to keep operations which are essentially identical, well, identical. I am looking for a way to pass the typed-pointer-containing 'sized-array' structs into the generic functions taking void-pointer-containing 'sized-array' arguments.
Long version, with involved example:
So, void pointers are wonderfully flexible, so I can do this:
int foo(void * ptr, size_t dataLen);
/* ... */
char * c;
size_t c_n;
/* ... */
foo(c, c_n);
/* ... */
int * i;
size_t i_n;
/* ... */
foo(i, i_n);
But since the pattern of "pointer to arbitrary length array, plus size there-of" is so common, suppose at some point I get tired of specifying my various functions in terms of pairs of arguments, pointer and length, and instead I start to code with such pairs encapsulated in a struct instead:
typedef struct
{
size_t v_n;
void * v;
}
pointerWithSize;
/* ... */
int foo(pointerWithSize);
So far so good. I can always assign my "char * c" or "int * i" into the pointerWithSize's "void * v" with minimal difficulty. But when you do this long enough, using the same pattern, you run into the following problem: Soon enough you have a bunch of general functions which work with the data agnostically, and are thus happy to take void pointers, for example things like:
pointerWithSize combinePointersWithSize(pointerWithSize p1, pointerWithSize p2);
int readFromStream(FILE * readFromHere, pointerWithSize * readIntoHere);
But you also end up with functions which are inherently intended for specific data types:
size_t countOccurancesOfChar(pointerWithSize str, char c);
int summate(pointerWithSize integers);
And then you end up with the annoyance of having to do casts inside the latter category of functions. E.g. you end up with stuff like this:
/* This inside countOccurancesOfChar */
if(((char * )str.m)[i] == c) {
/* ..or this inside summate: */
sum += ((int * )integers.m)[i];
So you get to a point where you have a lot of functions which operate specifically on "strings with size", and in all of those cases, you don't want to have to much around with void pointers. So instead, in those cases you start doing stuff like this:
typedef struct
{
size_t v_n;
char * v;
}
stringWithSize;
/* ... */
size_t countOccurancesOfChar(stringWithSize str, char c);
int parseFormatting(stringWithSize str, struct someFormat_t foo);
Which is great, because now all the string related code doesn't need to be cluttered with casts. BUT, now I can't use my wonderful generic function combinePointersWithSize to concatenate my strings contained within the stringWithSize, in a way that's as syntactically clean, as I could if I was still writing my functions in terms of two separate arguments for each pointer-and-size pair.
To finish up the illustration:
pointerWithSize combinePointersWithSize(pointerWithSize p1, pointerWithSize p2);
void * combineAlternative(void * p1, size_t p_n1, void * p2);
/* ... */
stringWithSize a, b, c;
/* ... */
/* This doesn't work, incompatible types: */
c = combinePointersWithSize(a, b);
/* But this works, because char * can be passed into void * parameter. */
c.v_n = a.v_n + b.v_n;
c.v = combineAlternative(a.v, a.v_n, b.v, b.v_n); /* Works fine. */
Possible Solutions I've Considered:
1: Don't write my functions with those structs as arguments, instead write them with individual pair arguments. But this is a big part of what I want to avoid in the first place - I like the 'cleanness' and clarity of intent that having a size_t and a pointer bundled in one struct represents.
2: Do something like this:
stringWithSize a, b, c;
/* ... */
pointerWithSize d;
d = combinePointersWithSize((pointerWithSize){.v=a.v, .v_n=a.v_n}, (pointerWithSize){.v=b.v, .v_n=b.v_n})
/* and then do either this: */
c.v = d.v;
c.v_n = d.v_n;
foo(c);
/* ..or this: */
foo((stringWithSize){.v=d.v, .v_n=d.v_n});
..but I think most would agree, this is also as bad or worse as the original problem of casting within the library functions. On the surface it looks worse, because it offloads the casting burden to the client code instead of library code which can hopefully be fairly stable after being implemented/completed (incl. testing/etc). On the other hand, if you did keep every function defined in terms of the void * containing pointerWithSize, you could end up forcing similar casts to the kind you're doing inside your own functions, elsewhere in their code, and worse, you're losing the advantage of the compiler yelling at you, because now the code is carrying everything within the same pointerWithSize struct.
I'm also concerned about how many compilers out there have the ability to optimize the first of the two variants of this solution away (where 'd' servers as merely a temporary result holder.
3: Union-of-pointers. Instead of my prior pointerWithSize example, I would do:
typedef union
{
void * void;
char * char;
int * int;
/* ...and so on... */
}
rainbowPointer;
typedef struct
{
size_t v_n;
rainbowPointer v;
}
pointerWithSize;
At first glance this is almost good enough. However, I very frequently end up wanting to store arrays of some struct which is specific to the program I'm working on inside this "pointer with size" construct, and in those cases, a predefined union of pointer types would be useless to me, I'd still be right back at this problem.
4: I could write wrapper functions for each permuted pointer type. I could EVEN write function-like macros to define each of these pointer-with-size struct types, which would in the same swoop generate the wrapper functions. For example:
#define pointerWithSizeDef(T, name) \
typedef struct \
{ \
size_t v_n; \
T * v;
} \
name; \
foo_ ## name (name p1) \
{ \
/* generic function code defined in macro */ \
/* Or something like this: */ \
foo((pointerWithSize){.v=p1.v, .v_n=p1.v_n});
};
/* Then, stuff like this: */
pointerWithSizeDef(char, stringWithSize)
My intuition is that sooner or later this method would become unwieldy.
5: If there is a mechanism with no performance impact, but which is unappealing otherwise, I could write my generic functions as function-like macros, which in turn invoke the underlying actual function:
int foo_actual(void * v, size_t v_n);
#define foo(p) \
foo_actual(p.v, p.v_n);
..or even something like this, to replace casting syntax:
#define castToPointerWithSize(p) \
((pointerWithSize){.v=p.v, .v_n=p.v_n})
/* ... */
stringWithSize a;
foo(castToPointerWithSize(a));
But as these examples for possible-solution-#5 show, I can't actually think of a way to do this that wouldn't quickly become a possible problem (e.g. if someone wanted to place a function call which returned a pointerWithSize in place of 'p' in the above examples - you'd be running the function twice, and it wouldn't be at all obvious from the code.
So I don't think any of the solutions I've thought of are really sufficient for my usecase, so I'm hoping some of you know of some C syntax or mechanism I could take advantage of here to make it easy to cast/"cast" between two structs which are identical save for the pointer type of one of their members.
Firstly, any kind of "actual" casting isn't going to be allowed per the letter of the standard, because C makes no guarantee at all that all pointers have the same format. A cast from some arbitrary pointer type to a void pointer is allowed to involve a conversion of representation (that gets reversed when you cast it back in order to access the data), including possibly to a different size of pointer or a pointer existing in a separate address space. So a simple reinterpretation of a bit pattern to change pointer type is not safe; void*'s bit pattern isn't guaranteed to mean anything in particular, and the bit patterns of other types aren't guaranteed to be related in any particular way. (How many systems actually take advantage of this, I have no idea.)
Since the explicit conversion between void* and other types has to exist somewhere, using whole-value conversion is probably the safest idea. What you could do is define a macro to quickly and easily generate "cast functions" for you, e.g.:
#define GEN_CAST(NAME, FROM_TYPE, TO_TYPE) \
static inline TO_TYPE NAME(FROM_TYPE from) { \
return (TO_TYPE){ .v=p.v, .v_n=p.v_n }; \
}
GEN_CAST(s_to_v, stringWithSize, pointerWithSize)
GEN_CAST(v_to_s, pointerWithSize, stringWithSize)
...that you can then use in place of the cast operator in expressions:
stringWithSize a, b, c;
pointerWithSize d;
d = combinePointersWithSize(s_to_v(a), s_to_v(b));
foo(v_to_s(d));
A good compiler should recognise that on common platforms the conversion function is an identity operation, and remove it entirely.
You should be able to cast one to another by converting one to a pointer, casting it to a pointer of the other type, and dereferencing it. This will work in reverse too.
struct charPtrWithLen
{
size_t len;
char * charPtr;
};
struct voidPtrWithLen
{
size_t len;
void * voidPtr;
};
int main() {
struct charPtrWithLen cpwl = {.len = 6, .charPtr = "Hello"};
struct voidPtrWithLen vpwl = *(struct voidPtrWithLen *)&cpwl;
return 0;
}
Note this will only work as long as the struct layout is the same for both structs.

C: Passing array to pointer function

I'm not sure if the question has asked before, but I couldn't find any similar topics.
I'm struggeling with the following piece of code. The idea is to extend r any time later on without writing lots of if-else statements. The functions (func1, func2...) either take zero or one arguments.
void func1() {
puts("func1");
}
void func2(char *arg){
puts("func2");
printf("with arg %s\n", arg);
}
struct fcall {
char name[16];
void (*pfunc)();
};
int main() {
const struct fcall r[] = {
{"F1", func1},
{"F2", func2}
};
char param[] = "someval";
size_t nfunc = RSIZE(r); /* array size */
for(;nfunc-->0;) {
r[nfunc].pfunc(param);
}
return 0;
}
The code above assumes that all functions take the string argument, which is not the case. The prototype for the pointer function is declared without any datatype to prevent the incompatible pointer type warning.
Passing arguments to functions that do not take any parameters usually results in too few arguments. But in this case the compiler doesn't 'see' this ahead, which also let me to believe that no optimization is done to exclude these unused addresses from being pushed onto the stack. (I haven't looked at the actual assemble code).
It feels wrong someway and that's usually a recipe for buffer overflows or undefined behaviour. Would it be better to call functions without parameters separately? If so, how much damage could this do?
The way to do it is typedef a function with 1 argument, so the compiler could verify if you pass the correct number of arguments and that you do not pass something absolutely incompatible (e.g. a struct by value). And when you initialize your array, use this typedef to cast function types.
void func1(void) { ... }
void func2(char *arg) { ... }
void func3(int arg) { ... }
typedef uintptr_t param_t;
typedef void (*func_t)(param_t);
struct fcall {
char name[16];
func_t pfunc;
};
const struct fcall r[] = {
{"F1", (func_t) func1},
{"F2", (func_t) func2}
{"F3", (func_t) func3}
};
...
r[0].pfunc((param_t) "foo");
r[1].pfunc((param_t) "bar");
r[2].pfunc((param_t) 1000);
Here param_t is defined as uintpr_t. This is an integer type big enough to store a pointer value. For details see here: What is uintptr_t data type.
The caveat is that the calling conventions for param_t should be compatible with the function arguments you use. This is normally true for all integer and pointer types. The following sample is going to work, all the type conversions are compatible with each other in terms of calling conventions:
// No problem here.
void ptr_func(struct my_struct *ptr) {
...
}
...
struct my_struct struct_x;
((func_t) &ptr_func)((param_t) &struct_x);
But if you are going to pass a float or double argument, then it might not work as expected.
// There might be a problem here. Depending on the calling
// conventions the value might contain a complete garbage,
// as it might be taken from a floating point register that
// was not set on the call site.
void float_func(float value) {
...
}
...
float x = 1.0;
((func_t) &float_func)((param_t) x);
In this case you might need to define a function like this:
// Problem fixed, but only partially. Instead of garbage
// there might be rounding error after the conversions.
void float_func(param_t param) {
float value = (float) param;
...
}
...
float x = 1.234;
((func_t) &float_func)((param_t) x);
The float is first being converted to an integer type and then back. As a result the value might be rounded. An obvious solution would be to take an address of x and pass it to modified a function float_func2(float *value_ptr). The function would dereference its pointer argument and get the actual float value.
But, of course, being hardcore C-programmers we do not want to be obvious, so we are going to resort to some ugly trickery.
// Problem fixed the true C-programmer way.
void float_func(param_t param) {
float value = *((float *) &param);
...
}
...
float x = 1.234;
((func_t) &float_func)(*((param_t *) &x));
The difference of this sample compared to passing a pointer to float, is that on the architecture (like x86-64) where parameters are passed on registers rather than on the stack, a smart enough compiler can make float_func do its job using registers only, without the need to load the parameter from the memory.
One option is for all the functions accept a char * argument, and your calling code to always pass one. The functions that don't need an argument need not use the argument they receive.
To be clean (and avoid undefined behaviour), if you must have some functions that accept no argument and some functions that accept an argument, use two lists and register/call each type of function separately.
If the behaviour is undefined there's no telling how much damage could be caused.
It might blow up the planet. Or it might not.
So just don't do it, OK?

How do I check if a variable is of a certain type (compare two types) in C?

In C (not C++/C#) how do I check if a variable is of a certain type?
For example, something like this:
double doubleVar;
if( typeof(doubleVar) == double ) {
printf("doubleVar is of type double!");
}
Or more general: How do I compare two types so that compare(double1,double2) will evaluate to true, and compare(int,double) will evaluate to false. Also I'd like to compare structs of different composition as well.
Basically, I have a function that operates on variables of type "struct a" and "struct b". I want to do one thing with the "struct a" variables and the other with the "struct b" variables. Since C doesn't support overloading and the void pointer losses its type information I need to check for type. BTW, what would be the sense in having a typeof operator, if you can't compare types?
The sizeof method seems to be a practical workaround solution for me. Thanks for your help. I still find it a bit strange since the types are known at compile time, but if I imagine the processes in the machine I can see, why the information is not stored in terms of types, but rather in terms of byte size. Size is the only thing really relevant besides addresses.
Getting the type of a variable is, as of now, possible in C11 with the _Generic generic selection. It works at compile-time.
The syntax is a bit like that for switch. Here's a sample (from this answer):
#define typename(x) _Generic((x), \
_Bool: "_Bool", unsigned char: "unsigned char", \
char: "char", signed char: "signed char", \
short int: "short int", unsigned short int: "unsigned short int", \
int: "int", unsigned int: "unsigned int", \
long int: "long int", unsigned long int: "unsigned long int", \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
float: "float", double: "double", \
long double: "long double", char *: "pointer to char", \
void *: "pointer to void", int *: "pointer to int", \
default: "other")
To actually use it for compile-time manual type checking, you can define an enum with all of the types you expect, something like this:
enum t_typename {
TYPENAME_BOOL,
TYPENAME_UNSIGNED_CHAR,
TYPENAME_CHAR,
TYPENAME_SIGNED_CHAR,
TYPENAME_SHORT_INT,
TYPENAME_UNSIGNED_CHORT_INT,
TYPENAME_INT,
/* ... */
TYPENAME_POINTER_TO_INT,
TYPENAME_OTHER
};
And then use _Generic to match types to this enum:
#define typename(x) _Generic((x), \
_Bool: TYPENAME_BOOL, unsigned char: TYPENAME_UNSIGNED_CHAR, \
char: TYPENAME_CHAR, signed char: TYPENAME_SIGNED_CHAR, \
short int: TYPENAME_SHORT_INT, unsigned short int: TYPENAME_UNSIGNED_SHORT_INT, \
int: TYPENAME_INT, \
/* ... */ \
int *: TYPENAME_POINTER_TO_INT, \
default: TYPENAME_OTHER)
C does not support this form of type introspection. What you are asking is not possible in C (at least without compiler-specific extensions; it would be possible in C++, however).
In general, with C you're expected to know the types of your variable. Since every function has concrete types for its parameters (except for varargs, I suppose), you don't need to check in the function body. The only remaining case I can see is in a macro body, and, well, C macros aren't really all that powerful.
Further, note that C does not retain any type information into runtime. This means that, even if, hypothetically, there was a type comparison extension, it would only work properly when the types are known at compile time (ie, it wouldn't work to test whether two void * point to the same type of data).
As for typeof: First, typeof is a GCC extension. It is not a standard part of C. It's typically used to write macros that only evaluate their arguments once, eg (from the GCC manual):
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
The typeof keyword lets the macro define a local temporary to save the values of its arguments, allowing them to be evaluated only once.
In short, C does not support overloading; you'll just have to make a func_a(struct a *) and func_b(struct b *), and call the correct one. Alternately, you could make your own introspection system:
struct my_header {
int type;
};
#define TYPE_A 0
#define TYPE_B 1
struct a {
struct my_header header;
/* ... */
};
struct b {
struct my_header header;
/* ... */
};
void func_a(struct a *p);
void func_b(struct b *p);
void func_switch(struct my_header *head);
#define func(p) func_switch( &(p)->header )
void func_switch(struct my_header *head) {
switch (head->type) {
case TYPE_A: func_a((struct a *)head); break;
case TYPE_B: func_b((struct b *)head); break;
default: assert( ("UNREACHABLE", 0) );
}
}
You must, of course, remember to initialize the header properly when creating these objects.
As other people have already said this isn't supported in the C language. You could however check the size of a variable using the sizeof() function. This may help you determine if two variables can store the same type of data.
Before you do that, read the comments below.
Gnu GCC has a builtin function for comparing types __builtin_types_compatible_p.
https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html
This built-in function returns 1 if the unqualified versions of the
types type1 and type2 (which are types, not expressions) are
compatible, 0 otherwise. The result of this built-in function can be
used in integer constant expressions.
This built-in function ignores top level qualifiers (e.g., const,
volatile). For example, int is equivalent to const int.
Used in your example:
double doubleVar;
if(__builtin_types_compatible_p(typeof(doubleVar), double)) {
printf("doubleVar is of type double!");
}
As others have mentioned, you can't extract the type of a variable at runtime. However, you could construct your own "object" and store the type along with it. Then you would be able to check it at runtime:
typedef struct {
int type; // or this could be an enumeration
union {
double d;
int i;
} u;
} CheesyObject;
Then set the type as needed in the code:
CheesyObject o;
o.type = 1; // or better as some define, enum value...
o.u.d = 3.14159;
As another answer mentioned, you can now do this in C11 with _Generic.
For example, here's a macro that will check if some input is compatible with another type:
#include <stdbool.h>
#define isCompatible(x, type) _Generic(x, type: true, default: false)
You can use the macro like so:
double doubleVar;
if (isCompatible(doubleVar, double)) {
printf("doubleVar is of type double!\n"); // prints
}
int intVar;
if (isCompatible(intVar, double)) {
printf("intVar is compatible with double too!\n"); // doesn't print
}
This can also be used on other types, including structs. E.g.
struct A {
int x;
int y;
};
struct B {
double a;
double b;
};
int main(void)
{
struct A AVar = {4, 2};
struct B BVar = {4.2, 5.6};
if (isCompatible(AVar, struct A)) {
printf("Works on user-defined types!\n"); // prints
}
if (isCompatible(BVar, struct A)) {
printf("And can differentiate between them too!\n"); // doesn't print
}
return 0;
}
And on typedefs.
typedef char* string;
string greeting = "Hello world!";
if (isCompatible(greeting, string)) {
printf("Can check typedefs.\n");
}
However, it doesn't always give you the answer you expect. For instance, it can't distinguish between an array and a pointer.
int intArray[] = {4, -9, 42, 3};
if (isCompatible(intArray, int*)) {
printf("Treats arrays like pointers.\n");
}
// The code below doesn't print, even though you'd think it would
if (isCompatible(intArray, int[4])) {
printf("But at least this works.\n");
}
Answer borrowed from here: http://www.robertgamble.net/2012/01/c11-generic-selections.html
From linux/typecheck.h:
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
Here you can find explanation which statements from standard and which GNU extensions above code uses.
(Maybe a bit not in scope of the question, since question is not about failure on type mismatch, but anyway, leaving it here).
This is crazily stupid, but if you use the code:
fprintf("%x", variable)
and you use the -Wall flag while compiling, then gcc will kick out a warning of that it expects an argument of 'unsigned int' while the argument is of type '____'. (If this warning doesn't appear, then your variable is of type 'unsigned int'.)
Best of luck!
Edit: As was brought up below, this only applies to compile time. Very helpful when trying to figure out why your pointers aren't behaving, but not very useful if needed during run time.
As of C2x, typeof is now a part of the language's standard. This allows the creation of a macro that compares the types of two values:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#define sametypeof(A,B) _Generic(A, typeof(B): true, default: false)
int main() {
if (sametypeof(1, 2)) {
printf("1 and 2 have the same type.\n");
} else {
printf("1 and 2 don't have the same type.\n");
}
}
(This compiles with the latest experimental version of GCC 13, using the -std=c2x flag)
If you want to compare between two types, you can use the following workaround:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#define sametype(A,B) _Generic(*((A*)0), B: true, default: false)
int main() {
if (sametype(void*, nullptr_t)) {
printf("void* and nullptr_t are the same type.\n");
} else {
printf("void* and nullptr_t are not the same type.\n");
}
}
Although *((A*)0) is not valid code at runtime, the compiler will still be able to deduce its type as A, so it will work in _Generic, as the code itself will not run and will be discarded. (as far as I remember, this trick has worked in every C11 compliant compiler I've used, including Clang and the Tiny C Compiler)
(you also cannot just do (A)0 because 0 cannot be cast to a struct)
C is statically typed language. You can't declare a function which operate on type A or type B, and you can't declare variable which hold type A or type B. Every variable has an explicitly declared and unchangeable type, and you supposed to use this knowledge.
And when you want to know if void * points to memory representation of float or integer - you have to store this information somewhere else. The language is specifically designed not to care if char * points to something stored as int or char.
One possible way is to have your variables names prepend your variable definitions with the type information.
Ex:
All integers will have i_
All floats will have f_
etc..
The variable name can be got out by the #<variable_name>,
This
There is a built-in function in GCC.
Built-in Function: int __builtin_types_compatible_p (type1, type2)
You can use the built-in function __builtin_types_compatible_p to determine whether two types are the same.
i've searched a solution to solve the issue of controlling data type for while , and i thought that maybe my founding could add up well with the initial demand #con-f-use, even if it's no exactly the same issue.
An other way around to control the datatype could be done using an union with predefined type. In my case, i had a defined structure in which i was originally using a void* to allow divers data type to be passed :
originally:
//[main]:
uint32_t vtest3= 100000;
int32_t vtest2= 100000;
struct entity list[] = {
{ TYPE_INT32, s_int32_t, .label="tension", &vtest3},
{ TYPE_INT32, s_int32_t, .label="tension", &vtest3}
};
//[file.h]:
struct entity {
enum entity_type type;
uint32_t dimension;
char* label;
void* ptr_data;
uint32_t offset;
};
enum entity_type {
TYPE_NONE = 0,
TYPE_INT8 = 1,
TYPE_INT16 = 2,
TYPE_INT32 = 3,
TYPE_INT64 = 4,
TYPE_UINT8 = 5,
TYPE_UINT16 = 6,
TYPE_UINT32 = 7,
TYPE_UINT64 = 8,
TYPE_FLOAT32 = 9
};
The issue with this method is that it accept all type of variable in an uncontrolled way. There is no easy method to control the data type referenced by the void* pointer, Excepted maybe thought the use of a macro and _Generic as described before in this thread.
If the programmer decided to pass a type different from the list of type accepted ,there while be no error thrown at compile time.
. They other way around is by replacing the void* by an union , this way the structure while only accept specific data type defined inside the union list . If the programmer decide to pass a pointer with an type which is not already defined inside the ptr_data union{...} , it will throw an error.
//[file.h]:
enum entity_type {
TYPE_NONE = 0,
TYPE_INT8 = 1,
TYPE_INT16 = 2,
TYPE_INT32 = 3,
TYPE_INT64 = 4,
TYPE_UINT8 = 5,
TYPE_UINT16 = 6,
TYPE_UINT32 = 7,
TYPE_UINT64 = 8,
TYPE_FLOAT32 = 9
};
struct entity {
enum entity_type type;
uint32_t dimension;
char* label;
union {
uint8_t *uint8;
uint16_t *uint16;
uint32_t *uint32;
uint32_t *uint;
int16_t *int16;
int32_t *int32;
int64_t *int64;
float *f;
} ptr_data;
uint32_t offset;
};
[main:]
uint32_t vtest3= 100000;
int32_t vtest2= 100000;
struct entity list[] = {
{ TYPE_INT32, s_int32_t, .label="a", .ptr_data = {.uint16=&vtest1}
},
{ TYPE_INT32, s_int32_t, .label="b", .ptr_data = {.int32=&vtest2}
};
This method make use of the union to control implicitly the data type of the variable inserted by the programmer in the structure. If not correct the compiler while throw an error at compile time.
Obviously this code example is far from perfect and cannot be used directly but i tried to explain in a way as clear as possible the logic and the the idea that i proposed ;)

Resources