pose
pose

Reputation: 21

Is there any way of finding out what type of struct a pointer points to?

My program contains several structs which only have one parameter in common. Ex:

struct first {
    var a;
    var b;
    var common_var;
    var c;
};

struct second {
    var d;
    var common_var;
    var e;
    var f;
};

The "common_var" is the parameter which all structs have in common, but it does not appear in the same order for the different structs. In the first-struct, it is the 3rd variable, and in the second-struct it is the 2nd variable.

Now, I have a function which takes a pointer-to-void as argument. I want to pass pointers to either of these structs, to this function, and do stuff based on the "common_var"-variable.

void main()
{
    struct first * pFirst;
    theFunctionIMentioned(pFirst);
}

void theFunctionIMentioned(void * p)
{
    /* Get hold of "common_var" parameter somehow. */
    /* Do something based on the "common_var" parameter. */
} 

If "common_var" was the first entry in all the structs, it wouldn't be a problem. I really want to avoid doing it that way, though.

So the question is: Can I find out somehow whether the function argument (void *p) is a pointer to a first-struct or a pointer to a second-struct?

EDIT 1: The problem is that this program has a UI which makes it possible (indirectly, of course) for the user to "decide" which struct pointer is sent to the function. If the user does action A, then the program passes a pointer-to-first to the function. If the user does action B, it passes a pointer-to-second to the function. However, the program cannot (under any circumstances) know whether action A or action B has been performed by the user. So basically, the only thing I "know" while programming is that the argument passed to the "theFunctionIMentioned()" is a pointer to a struct which contains "common_var". I am used to programming object oriented, and in that case I would have solved this by using some kind of interface-mechanism. I guess I am kind of hoping that there would be a similar code-technique in C.

Upvotes: 2

Views: 166

Answers (6)

hazzelnuttie
hazzelnuttie

Reputation: 1481

I believe you would be allowed to modify the function parameters. In that case,

void main() {

struct first * pFirst;
theFunctionIMentioned(pFirst, 1);

}

void theFunctionIMentioned(void * p, var decider) // decider = 1 for first
                                                  //         = 2 for second
                                                  //         = 3 for third 
{
      if (decider == 1)
      {
             struct first * pFirst = (struct first*) p;
       }

     else
     {
      }
} 

Upvotes: -1

Lundin
Lundin

Reputation: 213693

So the question is: Can I find out somehow whether the function argument (void *p) is a pointer to a first-struct or a pointer to a second-struct?

No, generally, there is no such method. The type information is lost when you convert to a void*.

It sounds like the UI needs to be rewritten. To have a function with void* that accepts several different structs already suggests a flawed program design - there should be different functions for the different cases. (Function pointers could be used to create a consistent interface.)

Work-arounds to solve this depends on what part of the code you are allowed to change.

Upvotes: 1

Thomas Padron-McCarthy
Thomas Padron-McCarthy

Reputation: 27632

No, a pointer, when the program runs, is just a memory address, and the memory pointed to is just bits. There are no hidden type tags.

(If you know what values the different fields in your structs can contain, and the bit patterns happen to be distinctive, it may be possible to write code that can determine, from the raw bits, what type of struct the pointer points to. Similar to a type field, but accidental. This would be complicated, error-prone, brittle and confusing, so I would almost never recommend it.)

Can you change the structs, or are they fixed? If you can change them, you can create a new struct, with a type field and a union consisting of your two structs. Or, you can insert a type field at the start of both structs.

If you can't change the structs, you'll need an extra parameter to tell the function what you are sending to it.

Upvotes: 2

Marievi
Marievi

Reputation: 5011

Structs first and second are different type of structs, defined by you. You cannot change the one into the other. When you declare a pointer to one of them, you can pass it to theFunctionIMentioned. But you will know its type, as you will have declared it.

Moreover, whether you pass a pointer to struct first or to struct second, you can access any of its variables by using pFirst->variable; where pFirst is the pointer you declared and variable the variable you want.

Upvotes: 0

Hugo
Hugo

Reputation: 254

In C variable names are present only during the compile and link step, but in runtime they aren't available. You must think of a different solution by which you can access the value. One such case could be

void main()
{
    struct first * pFirst;
    theFunctionIMentioned(pFirst, pFirst->common);
}

void theFunctionIMentioned(void * p, var common)
{
    /* Get hold of "common_var" parameter somehow. */
    /* Do something based on the "common_var" parameter. */
} 

Upvotes: 1

Rishikesh Raje
Rishikesh Raje

Reputation: 8614

The two structs mentioned are not interchangeable. A pointer to first cannot be converted to a pointer to second. Even if you typecast it, the underlying data organization cannot be changed.

I would suggest that you take the common parameter common_var as a parameter to the function and use it in that way.

void theFunctionIMentioned(var common_var)

void main()
{
    struct first * pFirst;
    theFunctionIMentioned(pFirst->common_var);
}

Upvotes: 1

Related Questions