_Generic can select between different statements based on the type of the variable passed, however (as somewhat expected) it fails if these statements contain type names themselves. As an example:
#define PROMOTE(var) \
_Generic((var), \
char: int);
int main() {
char c;
PROMOTE(c) i = 0;
return 0;
}
One might expect the above code to work, with the line using PROMOTE evaluating to "int i = 0", but alas, it does not compile. I tried some roundabout ways to write the type (int), such as with a macro (#define TYPE_int int) or a typedef (typedef int TYPE_int), but to no avail. This is most probably intended (or purposefully undefined) behavior, but I'm still interested in the possibility, even if it requires some C wizardry.
In light of that, how can one make _Generic output a type?
Note: Solutions should rely only on standard C (i.e. no compiler specific constructs).
The closest thing I can imagine is combination of _Generic, compound literals and typeof extension available in popular compilers like GCC and CLANG.
#include <stdio.h>
struct SomeStruct { int x; };
#define PROMOTE(X) typeof(_Generic((X){0}, char: (int){0}, int: (float){0}, float: (struct SomeStruct){0}))
int main() {
PROMOTE(char) a = 1;
PROMOTE(int) b = 2.0f;
PROMOTE(float) c = { .x = 42 };
printf("%d\n", a);
printf("%f\n", b);
printf("%d\n", c.x);
return 0;
}
prints
1
2.000000
42
Unfortunately, This is not standard C.
I was wondering if it would be a good idea to use structs as pseudo namespaces (à la C++) to group constants which are functionally or conceptually related to each other.
static const struct {
const unsigned int START;
const unsigned int END;
} COUNTER = {.START = 1, .END = 100};
Is there any downside to this? If not, is it redundant (or maybe even unconvenient) to have both the struct instance and its members declared as const? Where should the constantness of these values be stated?
I was wondering if it would be a good idea to use structs as pseudo namespaces
Well, it CAN be a good idea. It's not intrinsically bad. An argument against is that if you feel that you need namespaces, then it's likely that C is the wrong language in the first place. But it can be used this way, and it is sometimes used this way.
Where should the constantness of these values be stated?
It's in general enough to declare the whole struct as const. But beware with pointers. This code is valid and will print "42":
int x = 5;
const struct {
int *p;
} S = {.p = &x };
int main()
{
*(S.p) = 42;
printf("%d\n", x);
}
In the above code, you are not allowed to change S.p so that it points to something else, but there is a difference between a const pointer and a pointer to const. So for pointer, it could be a good idea to add an extra const.
To clarify, the pointer p will be declared like it was a int * const p which means you cannot change the pointer itself, but in order to protect the data it's pointing to, you need const int *p. To get both, use const int * const p, but if the struct is declared as const, you'll get one of them "for free" so const int *p is enough to get both.
And if you consider pointers to pointers, well, think it through for a long time and test it to make sure it works the way you want.
From comments:
Why not enums?
Because this is not valid:
enum S {a = 5};
enum Y {a = 6};
The compiler will tell you that a is already defined. So enums is not good for emulating namespaces. Also, you cannot use enums for non-integers.
Is it a good practice to group related constants using structs in C?
It's opinion based. If it works for you, do it.
I wouldn't do like that i C. Instead I use #define
Like:
#define GROUPNAME_NAME
so in your case I would do
#define COUNTER_START 1
#define COUNTER_END 100
In C++ I would do:
const unsigned int COUNTER_START = 1;
const unsigned int COUNTER_END = 100;
The difference between C and C++ is due to differences in language specification.
I think that GCC extension __attribute__((cleanup)) is a good idea, at least for some cases, but i can't figure out how to use it in a good way. All i'm doing looks still really annoying.
I saw a lot of code doing #define _cleanup_(x) __attribute__((cleanup(x)) just to type less, but it there a way to pass there a standard function like free or closedir, fclose, etc?
As I see I can't just write:
__attribute__((cleanup(free))) char *foo = malloc(10);
Because the cleanup callback will receive char** pointer, and I have to always write something like:
static void free_char(char **ptr) { free(*ptr); }
__cleanup__((free_char)) char *foo = malloc(10);
That's pretty annoying, and the most annoying part is to define such cleanup functions for all types you need, because obviously you can't just define it for void **. What is the best way to avoid these things?
You can't write __attribute__((cleanup(free))), but you don't need to write a free cleanup function for each type. It's ugly, but you can write this:
static void cleanup_free(void *p) {
free(*(void**) p);
}
I first saw this in the systemd codebase.
For other functions you would in general need to a write a wrapper with an extra level of indirection for use with __attribute__((cleanup)). systemd defines a helper macro for this:
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
func(*p); \
} \
struct __useless_struct_to_allow_trailing_semicolon__
which is used all over the place, e.g.
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
#define _cleanup_pclose_ __attribute__((cleanup(pclosep)))
There's a library that builds general-purpose smart pointers (unique_ptr and shared_ptr) on top of __attribute__((cleanup)) here: https://github.com/Snaipe/libcsptr
It allows you to write higher-level code like this:
#include <stdio.h>
#include <csptr/smart_ptr.h>
#include <csptr/array.h>
void print_int(void *ptr, void *meta) {
(void) meta;
// ptr points to the current element
// meta points to the array metadata (global to the array), if any.
printf("%d\n", *(int*) ptr);
}
int main(void) {
// Destructors for array types are run on every element of the
// array before destruction.
smart int *ints = unique_ptr(int[5], {5, 4, 3, 2, 1}, print_int);
// ints == {5, 4, 3, 2, 1}
// Smart arrays are length-aware
for (size_t i = 0; i < array_length(ints); ++i) {
ints[i] = i + 1;
}
// ints == {1, 2, 3, 4, 5}
return 0;
}
As for idiomatic, though? Well the above is certainly close to idiomatic C++. Not C so much. The feature is clearly mainly supported in GCC and Clang because they have C++ compilers as well, so they have the option to make use of the RAII machinery in the C frontend at no extra cost; that doesn't make it a great idea to write C-intended-as-C this way. It kinda relies on a C++ compiler being present despite not actually being used.
If it were me, I'd probably investigate implementing autorelease pools, or something similar that can actually be done in pure C at the language level. Depends how quickly you need your resources to be freed; for memory, you usually can live without immediate cleanup.
I've run into a problem when attempting to express the pointer to a type within a macro.
Take this simple example.
#define INDEX_OF_DATA(data, type, index) \
((type *)data)[index]
This works:
INDEX_OF_DATA(buffer, float, 3);
Where this fails:
INDEX_OF_DATA(buffer, float[2], 3);
Because the cast should be (float(*)[2]).
Is there a way to express "the pointer of a type", ...without using typeof? (which isn't standard C).
Note, there are of course other ways to make this specific example work. cast to char and offset by sizeof(type) * index for example. But am interested in a way to express pointer to type in C.
Doing heavily complicated stuff with C types may be a fun sport, but it's extremely confusing in real code.
To avoid wrecking their heads over complicated pointer expressions too much, people often use typedef!
If you typedef all the types that you expect to use with this macro of yours, you won't have any problems. Observe:
#include <stdlib.h>
#define INDEX_OF_DATA(data, type, index) \
((type *)data)[index]
int main(void) {
float (*buffer)[2] = malloc(4 * sizeof(float[2]));
typedef float t_f2arr[2];
INDEX_OF_DATA(buffer, t_f2arr, 3)[0] = 1.1f;
return 0;
}
This does exactly what you intended!
If we want to preserve the original macro, we can use this trick:
#define INDEX_OF_DATA(data, type, index) ((type*)data)[index]
struct mystruct { float f[2]; };
mystruct* p = &INDEX_OF_DATA(buffer, mystruct, 3);
Unfortunately this solution could be affected by struct padding so it's better to check:
static_assert(sizeof(mystruct) == sizeof(float (*)[2]), "padding found");
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 ;)