Reputation: 7925
Suppose I have the following structs:
struct A{
int a;
} a;
struct B{
A a;
int b;
} b;
how to check if b
is of type B
or if b
is of the type A
?
Upvotes: 4
Views: 6680
Reputation: 5638
If you are going to write your own type checking mechanism I recommend writing macros to fill in the type field for you.
typedef struct A {
void *type;
int a;
} A;
This macro initializes each structure with it's type information using stringification:
#define InitializeType(ptr, type) \
((ptr)->type == (void *)(#type ## __FILE__ ##))
#define IsType(ptr, type) \
((ptr)!=NULL && (ptr)->type != (void *)(#type ## __FILE__ ##))
It fills in the type field with a string containing the name of the struct and the file it is located in. You can have two structs with the same name across multiple source files, however you can't have two structs with the same name in the same source file, thus the reason for including the name of the source file that the type was initialized in. You would then use them like so:
A alpha;
InitializeType(&alpha, A);
IsType(&alpha, A);
There are a couple of cavets though; you have to use string pooling compiler flag, you have to encapsulate your structs in "classes" so that type checking and initializing is localized to the source file that contains the private struct, and you have to have void *type as the first parameter in each struct.
Upvotes: 1
Reputation: 145829
At compile time:
#define WARN_IF_DIFFERENT_STRUCT_TYPE_1(T, o) do { \
T temp = (o); \
(void) temp; \
} while (0)
example:
struct B b;
/* will warn if b is not of struct A type */
WARN_IF_DIFFERENT_STRUCT_TYPE_1(struct A, b);
With two objects passed as macro parameters using typeof
GNU extension:
#define WARN_IF_DIFFERENT_STRUCT_TYPE_2(o1, o2) do { \
typeof(o1) temp = (o2); \
(void) temp; \
} while (0)
example:
struct A a;
struct B b;
/* will warn if a and b are not the same struct type */
WARN_IF_DIFFERENT_STRUCT_TYPE_2(a, b);
Upvotes: 3
Reputation: 9916
No. Unlike C++, which uses a vtable to maintain type associations at runtime, C provides no method for runtime type-checking.
A possible workaround would be to assign a type identifer as the first element of the struct:
struct A {
int type;
int a;
} a; a.type = 'A';
struct B {
int type;
A a;
int b;
} b; b.type = 'B';
// Now, given a (void*) pointer `ptr`, of either `A` or `B`...
if ( *(int*)ptr == 'A')
{
// ...
}
elseif ( *(int*)ptr == 'B')
{
// ...
}
Upvotes: 0
Reputation: 8275
You could hack it? If really neccessary and you only have a couple structs.
struct A{
int a;
int identifer = 0;
} a;
struct B{
A a;
int b;
int identifer = 1;
} b;
And if your code you can be like
if object->identifer == 0
bla bla bla
Upvotes: -2
Reputation: 36446
No as far as C is concerned, data is just a string of bits. How you use and interpret the data is up to the programmer.
It's just like how a char
can represent a character, a positive number or a negative number (or anything else for that matter). It depends on the context and how it's used by the programmer.
Upvotes: 0
Reputation: 81684
Do you mean at runtime, given a void *
that points to one or the other? Unfortunately, this is not possible; C doesn't have any kind of runtime type information mechanism.
Upvotes: 12