4

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?

5
  • 2
    Just look at the declaration? Commented Jun 5, 2012 at 20:15
  • Are you referring to checking programmatically at runtime? Commented Jun 5, 2012 at 20:16
  • 2
    There is no type B or type A. There is type struct B, and that's what b is. Commented Jun 5, 2012 at 20:16
  • 2
    If this were C++ there would be several ways you can do this, but assuming you really meant C when you tagged it as such you can't make such a check. Commented Jun 5, 2012 at 20:20
  • 1
    Take a look at pattinson.demon.co.uk/program/prog_rtti.htm "RTTI in C" Commented Jun 5, 2012 at 20:25

6 Answers 6

12

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.

Sign up to request clarification or add additional context in comments.

3 Comments

So I must include a field "type" with some value and check that value in order to find the "type"? :(
@Fabricio: The usual way is to use some variation of struct { int type; union { type1 t1; type2 t2 } data }
@Fabricio - See my answer for an example.
3

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);   

2 Comments

You don't need a gnu extension: typedef char dummy[sizeof(1 ? A : B)] would do to detect if types A and B are compatible (after eventual conversion to an rvalue).
@JensGustedt yes, nice one I didn't think of the conditional operator
1

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.

Comments

0

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.

Comments

0

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') { // ... } 

8 Comments

That cannot possibly work if you have only a pointer to the object
@DanF - On the contrary, it is possible to have a (void*) pointer and know nothing about the object's type. See the comment included in my example.
@Unsigned: The code was entirely different when I commented. Also, I'm not sure this is guaranteed to work by the C standard.
@NiklasB. - Ah, I was revising it and mistakenly saved an incomplete revision. What is not guaranteed to work?
if ( (int*)ptr == 'B' ) at the very least, you ought to dereference the pointer. I suppose that's just a typo, though. If the pointer you get is a valid pointer to something that is guaranteed to be either a struct A or a struct B, it will work, though.
|
-2

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 

7 Comments

being able to access object->identifier implies you know about its type already
@DanF not if you have it in both (all) structs. Again its a hack. The only thing I'm not so sure about is setting those default values...
@Flo you would also have to have exactly the same data structure between the two types, or you have no idea what you'll actually get when you access object->identifier
@DanF No. You only need the one common "identifier" in all of them and therefore you can access it from any type of object. Again I just don't think you can set the values for that identifier in the struct definition.
@Flo: it's an ugly hack, but you might get it to work if (and only if!) that field was the first one in each struct. Much cleaner to use a union, given that you're going to modify all the structs anyway.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.