How to pass a structure element structure to function by pointer - c

I am trying to change my C functions of nested structures to operate on pointers instead of passing and making copies of the structures which are quite large in reality.
here is a simplified version of what I want to do passing the structures around....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
outer1 = get_outer ();
}
struct OuterStruct get_outer (void)
{
struct OuterStruct thisOuter;
thisOuter.inner1 = get_inner (void);
thisOuter.outerResult = get_result (thisOuter.inner1);
return thisOuter;
}
struct InnerStruct get_inner (void)
{
struct InnerStruct thisInnner;
thisInner.int1 = 1;
thisInner.int2 = 2;
return thisInner;
}
int get_result (struct InnerStruct thisInner)
{
int thisResult;
thisResult = thisInner.int1 + thisInner.int2;
return thisResult;
}
but the structure is quite large in reality and this is a frequent operation, so I'd rather pass around the pointers. Just not sure how the syntax works for nested structures like this. Here is my attempt....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
get_outer (&outer1);
}
void get_outer (struct OuterStruct *thisOuter)
{
get_inner (&(thisOuter->inner1));
thisOuter->outerResult = get_result (&(thisOuter->inner1));
}
void get_inner (struct InnerStruct *thisInner)
{
thisInner->int1 = 1;
thisInner->int2 = 2;
}
int get_result (struct OuterStruct *thisInner)
{
int thisResult;
thisResult = thisInner->int1 + thisInner->int2;
return thisResult;
}

You should really look up more about how pointers work. But here is some sample C++ code. Notice the "&" tells your compiler to "not send the struct itself" to the function but a pointer to it. Just a warning never return a reference to a variable (unless you know what you are doing).
#include <iostream>
struct MyStruct
{
int a;
int b;
};
using namespace std;
void printStruct(MyStruct * mypointer) {
cout << "MyStruct.a=" << mypointer->a << endl;
cout << "MyStruct.b=" << mypointer->b << endl;
}
int main()
{
MyStruct s;
s.a = 2;
s.b = 1;
printStruct(&s);
return 0;
}

This will illustrate an easy way to pass pointers to structs. It is a much more efficient way to pass data around, especially when, as you say, the data can get very large. This illustration uses a compound struct, (struct within struct) with an array and pointer declared to pass around. Comments in code explain things.
This will all build and run so you can experiment with it. i.e., follow the data along with execution.
Here is an easy way: (using my own structs)
typedef struct {
int alfha;
int beta;
} FIRST;
typedef struct {
char str1[10];
char str2[10];
FIRST first;
}SECOND; //creates a compound struct (struct within a struct, similar to your example)
SECOND second[5], *pSecond;//create an array of SECOND, and a SECOND *
SECOND * func(SECOND *a); //simple func() defined to illustrate struct pointer arguments and returns
int main(void)
{
pSecond = &second[0]; //initialize pSecond to point to first position of second[] (having fun now)
SECOND s[10], *pS; //local copy of SECOND to receive results from func
pS = &s[0];//just like above;
//At this point, you can pass pSecond as a pointer to struct (SECOND *)
strcpy(pSecond[0].str2, "hello");
pS = func(pSecond);
// printf("...", pS[0]...);//pseudo code - print contents of pS, which now contains any work done in func
return 0;
}
SECOND * func(SECOND *a) //inputs and outputs SECOND * (for illustration, i.e., the argument contains all
{ //information itself, not really necessary to return it also)
strcpy(a[0].str1, "a string");
return a;
}
Although there is not much going on in func(), when the pointer returns to main(), it contains both the value copied in main, and the value copied in fucn(), as shown here:
Results: (in code)
Contents in pSecond:

Related

object oriented C - variables in struct + pro's and cons

I am a young student who learned C two years ago. I just discovered more complex things like object oriented C.
My first question is:
1) How do you access your variables? The goal would be to have specific values for those variables depending on the struct which has been instantiated.
So I'd like something like:
myStruct* myStrPtr;
myStruct2* myStrPtr;
myStrPtr = initializeStruct();
myStrPtr->printContent //prints for example 55
myStrPtr2 = initializeStruct();
myStrPtr2->printContent //prints for example 6548
example
typedef struct {
void (*sum)(int a, int b);
void (*printContent)(void);
int content;
}myStruct;
void printInhoud(void){
printf("content: %d\n", content);}
void sum(int a, int b){
/***********THIS DOESN T WORK OBVIOUSLY************/
this->content = a+b;
printf("calculated sum: %d", sum);
}
myStruct * initializeStruct(void)
{
myStruct* myStrPtr = malloc(sizeof(myStruct));
myStrPtr -> foo = foo ;
mynStrPtr->printContent = printContent;
return myStrPtr;
}
void freeMem(myStruct * myStructPtr)
{
free(myStructPtr);
}
int main (void)
{
int a= 1;
int b=33;
myStruct* myStrPtr;
myStrPtr = initializeStruct();
myStrPtr->printContent();
return 0;
}
2) my second question is: what are pro's and con's about programming in this way? I think that if I am able to add the variables in the structures and access them just like in OOP, I get a big advantage: modularity. I am active in embedded software and believe that having such an advantage of OOP on an embedded system can be very interesting. I have been criticized for trying to do this. The only reason I was given: "You have no garbage collector, so don't". Could someone give me some pro's and con's and explain why this would be "such an incredibly bad programming practice"
You can do OOP in C, but one of the major cons is that you have to pass the this pointer around. Let's say you have a pointer to a printInfo() function in your struct and you want to print the info of that particular struct. You have to do
my_struct->printInfo(my_struct);
or, if my_struct is not a pointer to your struct
my_struct.printInfo(&my_struct);
There's no way around it.
For your second question, I'm not sure doing OOP in C is really practical. I have done it out of curiosity and it's really fun. You can get inheritance, virtual base classes, polymorphism and all. If you're interested you can check it out here:
https://github.com/vladcc/object-oriented-c
Disclaimer: I'm not sure that the following is truely an answer, but it is way too long for a comment.
Is it possible to do OOP in C?
Yes it is. First C++ compilers were mere pre-processors that converted C++ source to C. Of course, you have neither contructors not destructors so you must explicitely call them, you must use composition pattern for inheritance, you must have vtables for virtual methods and must explicitely pass the this pointer.
Simple example with ctor, dtor, a dynamic array and a method:
struct __foo {
int *arr;
int n;
};
typedef struct __foo foo;
bool init_foo(foo *f, int n) {
f->arr = malloc(n * sizeof(int));
f->n = n;
return (f->arr != NULL);
}
void clean_foo(foo *f) { free(f->arr); }
bool set(int index, int value, foo *f) { // same for get...
if ((index >= f->n) || (index < 0)) return false;
f->arr[index] = value;
return true;
}
Usage:
foo f;
init_foo(8, &f);
set(5, 2, &f);
clean_foo(&f);
More complex example with inheritance and virtual method :
typedef struct {
int age;
const char *name;
const char* (*say)(void *);
} animal;
typedef struct {
animal parent;
} dog;
typedef struct {
animal parent;
} cat;
void init_animal(int age, const char *name, animal *a) {
a->age = age;
a->name = name;
}
char *pre_say(animal *this) {
char * msg = malloc(strlen(this->name) + 11);
strcpy(msg, this->name);
strcat(msg, " says ");
return msg;
const char * wow(void *an) {
animal *this = (animal *) an;
char * msg = pre_say(this);
strcat(msg, "Woof");
return msg;
}
const char* meeow(void *an) {
animal *this = (animal *) an;
char * msg = pre_say(this);
strcat(msg, "Meew");
return msg;
}
void init_dog(int age, const char * name, dog *d) {
init_animal(age, name, &(d->parent));
d->say = &woof;
}
void init_cat(int age, const char * name, cat *c) {
init_animal(age, name, &(c->parent));
d->say = &meeow;
}
Usage example:
dog d;
init_dog(2, "Rintintin", &d);
cat c;
init_cat(3, "Tom", &c);
const char *msg = (d.say)(&d); // msg <- Rintintin says Woof
free(msg);
msg = (c.say)(&c); // msg <- Tom says Meew
free(msg);
Should we do OOP in C?
Definitely NO. As you can say from previous example, as soon as you need polymorphism, pointers must be void * and you loose all possible type checking. And you also loose all the C++ goodies of automatic construtors and destructors, automatic this pointer, etc. You end with much more code, much harder to read and debug. The only acceptable use cases (IMHO) are:
interfacing C++ and C
minimal conversion of C++ code for a platform where you have only a C compiler.
low level codes (kernel or high performance libraries) in which you do not want to be bored with the overhead of C++, and still need OOP.
And just remember: if C++ was invented, it must have been to fill a gap in C language. So don't try to do what C++ was created for in C, unless you really know why you do that.
Has Garbage Collector something to do with OOP?
Here again no. C++ has no garbage collection and is indeed an OO language.
Not only encapsulation, many other OOP concepts can be implemented using C with little bit effort.
Here is an example.
//
// cobj.h
//
#ifndef __COBJ_H__
#define __COBJ_H__
struct _cobj_priv;
typedef struct _cobj {
struct _cobj_priv *priv;
void (*set_data)(struct _cobj *obj, int data);
int (*get_data)(struct _cobj *obj);
void (*print_data)(struct _cobj *obj);
} cobj_t;
cobj_t *new_struct(void);
void free_struct(cobj_t *obj);
#endif /* __COBJ_H__ */
//
// cobj.c
//
#include "cobj.h"
#include <stdio.h>
#include <stdlib.h>
//
// Internal section
//
struct _cobj_priv {
int data;
};
static void set_data (struct _cobj *obj, int data) {
struct _cobj_priv *this = (obj && obj->priv) ? obj->priv: NULL;
if (this) {
this->data = data;
}
}
static int get_data (struct _cobj *obj) {
struct _cobj_priv *this = (obj && obj->priv) ? obj->priv: NULL;
return (this)? this->data : 0;
}
static void print_data (struct _cobj *obj) {
struct _cobj_priv *this = (obj && obj->priv) ? obj->priv: NULL;
if (this)
printf("%d\n", this->data);
}
//
// APIs section
//
cobj_t *new_struct(void) {
cobj_t *obj = malloc(sizeof(cobj_t));
if (obj) {
obj->priv = malloc(sizeof(struct _cobj_priv));
if (obj->priv) {
obj->priv->data = 0;
}
obj->set_data = &set_data;
obj->get_data = &get_data;
obj->print_data = &print_data;
}
return obj;
}
void free_struct(cobj_t *obj) {
if (obj) {
if (obj->priv)
free(obj->priv);
free(obj);
obj = null;
}
}
//
// main.c
//
#include "cobj.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
cobj_t *obj = new_struct();
if (obj) {
obj->print_data(obj);
obj->set_data(obj, 100);
obj->print_data(obj);
printf("> get data return %d\n", obj->get_data(obj));
}
return 0;
}
Result:
0
100
> get data return 100
In C, struct's methods are function pointers, they do not know about the existence of struct so that they can not access to the struct members. You need to pass the struct instance to methods as a parameter in order to access to its members.

Defining a program local pointer of a structure

my question deals with creating variables that are visible throughout the program file. In other words, a file-local variable.
Consider this example
#include <stdio.h>
struct foo
{
char s[] = "HELLO";
int n = 5;
};
struct foo *a;
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a->s);
printf("%d\n",a->n);
return 0;
}
Now, this code snippet won't run.
Why?
Because the structure pointed to be pointer variable a will not get allocated as the statement never executed.
Now, how do you get it allocated without changing the scope of this variable a?
#include <stdio.h>
struct foo {
char const *s;
int n;
};
/* static for file-local */
static struct foo a = { "HELLO" , 5 };
int main(void) {
printf("%s\n", a.s);
printf("%d\n", a.n);
return 0;
}
Now, how do you get it allocated without changing the scope of this variable a?
I am sure there a lot of ways to solve your problem. Here's my suggestion.
Change the definition of struct foo to contain a fixed number of characters in s.
Create a as an object instead of a pointer. Initialize it with the necessary values.
Make a a static variable so its use is limited to the file only.
Use the object a instead of the pointer a in rest of the file.
#include <stdio.h>
struct foo
{
char s[20];
int n;
};
static struct foo a = {"HELLO", 20};
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
return 0;
}
This:
struct foo
{
char s[] = "HELLO";
int n = 5;
};
Is not valid C code. You first declare the type:
struct foo
{
char s[10];
int n;
};
Then define a variable of that type:
static struct foo a = { "HELLO", 5 };
The static keyword allows this variable to have file local scope.
You can now use it like this:
static struct foo a = { "HELLO", 5 };
void other()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
}
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
other();
return 0;
}
Note that a is accessible from both functions. It will not however be viewable from functions defined in other files because it is declared as static.
As for using a pointer vs the struct directly, you can take the address of this structure at any time you need to use it in that way:
some_function(&a);
well, i need to use a pointer instead of a structure directly
Try this:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
struct foo{
char s[20];
int n;
};
int main(void){
struct foo *a;
a = malloc(sizeof(struct foo));
puts("Dummy outputs!\n");
strcpy(a->s, "HELLO");
a->n = 5;
printf("%s\n",a->s);
printf("%d\n",a->n);
free(a);
return 0;
}
Output:
Dummy outputs!
HELLO
5

How to typecast void pointer based on condition?

To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...

Equivalent of std::bind in C by hacking the stack

After some research I didn't find a good way to implement the std::bind in C.
I build a small program that implements an equivalent of std::bind in C by hacking the stack.
There's two functions I will try to bind to function with pre-defined arguments.
My problem is this code is only working under Windows. Under Linux, this is a mess. I this the problem is my knowledge of the stack and the way that arguments are store in memory.
Thanks,
Please, find below the code I made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
The two functions I want to bind :
void test1 (int nombre, char t, int nombre2)
{
printf ("test 1 : %d%c%d\n", nombre, t, nombre2);
}
void test2 (char t, int nombre, int nombre2)
{
printf ("test 2 : %c%d%d\n", t, nombre, nombre2);
}
Two struct that will store the argument of each function (order of fields is important).
typedef struct {
int nombre;
char t;
int nombre2;
} struct1;
typedef struct {
char t;
int nombre;
int nombre2;
} struct2;
This "fake" struct will be use to write on the stack by dereferencing a structvoid* variable.
// Size must be bigger than every struct*
typedef struct {
int i[10];
} structvoid;
The main function.
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
void *func2 = (void *)&test2;
void (*functionPtrc)(structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
void *datac = malloc (sizeof (structvoid));
memcpy(datac, &data1, sizeof (struct1));
data[0] = (structvoid*)datac;
functions[0] = func1;
// Same thing with function 2.
struct2 data2;
data2.t = 'a';
data2.nombre = 5;
data2.nombre2 = 10;
datac = malloc (sizeof (structvoid));
memcpy(datac, &data2, sizeof (struct2));
data[1] = (structvoid*)datac;
functions[1] = func2;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// All the hack is here. By dereferencing the data, this will write on the stack all arguments need by the test1 function.
functionPtrc(*data[0]);
functionPtrc = functions[1];
functionPtrc(*data[1]);
// To check the result.
test1 (data1.nombre, data1.t, data1.nombre2);
test2 (data2.t, data2.nombre, data2.nombre2);
return 0;
}
EDIT
Here a new version of the program by calling function via the calling convention. I only wrote the new lines. The problem of this method is I can only store data inside a "void *" field. If I increase the size of structvoid, I got garbage behaviors.
// Structure that memories each argument
typedef struct {
void *i[1];
} structvoid;
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
// Let's start with a maximum of 5 arguments
void (*functionPtrc)(structurevoid, structurevoid, structurevoid, structurevoid, structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
structvoid *datac = malloc (sizeof (structvoid)*5);
memcpy(&datac[0], &data1.nombre, sizeof (data1.nombre));
memcpy(&datac[1], &data1.t, sizeof (data1.t));
memcpy(&datac[2], &data1.nombre2, sizeof (data1.nombre2));
data[0] = datac;
functions[0] = func1;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// Call the function with the arguments. The unused argument will be ignored.
functionPtrc(data[0][0], data[0][1], data[0][2], data[0][3], data[0][4]);
}

Receive pointer to different structs in different calls as an argument (or something like that)

For example, assume I have something like this:
typedef struct one
{
int data;
int dogs;
}One;
typedef struct two
{
int data;
int birds;
}Two;
typedef struct three
{
int data;
int cats;
}Three;
void swapData(???* elem1, ???* elem2) //<- the problem is here
{
int temp = elem1->data;
elem1->data = elem2->data;
elem2->data = temp;
}
int main()
{
One dog;
Two bird;
Three cat;
dog.data = 1;
bird.data = 2;
cat.data = 3;
swapData(&dog, &cat);
swapData(&dog, &bird);
swapData(&bird, &cat);
return 0;
}
What do I have to put in place of the ??? for the function to accept pointers to either One, Two or Three structs as arguments?
I tried void but then I can't access the structs' fields...
If you always define the data first in each struct, and data is always an int, then you can do something like this:
void swapData(void* elem1, void* elem2) //<- the problem is here
{
int* e1 = (int*) elem1;
int* e2 = (int*) elem2;
int temp = e1[0];
e1[0] = e2[0];
e2[0] = temp;
}
the reason this works is because when you pass a void *, you get memory of size sizeof(One) or whatever you put in. since the data is first, we can just pretend that you passed in an array of integers, and take the first one. If you had a more complicated structure, you could build a struct where the first few elements are the same types as any struct you might pass in. this way you could manipulate multiple objects. that would look something like this:
typedef struct {
int data;
char * name;
...
} complicated;
typedef struct {
int data;
char * name;
int something_else;
} simple;
typedef struct { // least common denominator
int data;
char * name;
} common;
void swap(void * e1, void* e2){
common* c1 = (common*) e1;
common* c2 = (common*) e2;
int tmp = c1->data;
char * tmpn = c1->name;
c1->data = c2->data;
c1->name = c2->name;
c2->data = tmp;
c2->name = tmp;
}
hope this makes sense.
You can't do that, you have ti write 3 separate functions to achieve this...
void swapData13(one *elem1, three*elem2)
{
int temp = elem1->data;
elem1->data = elem2->data;
elem2->data = temp;
}
void swapData12(one *elem1, two*elem2)
{
int temp = elem1->data;
elem1->data = elem2->data;
elem2->data = temp;
}
void swapData23(two *elem1, three*elem2)
{
int temp = elem1->data;
elem1->data = elem2->data;
elem2->data = temp;
}
Also the way you are passing parameter in main is wrong...
You can do...
swapData13(&dog, &cat);
swapData12(&dog, &bird);
swapData23(&bird, &cat);
Out of curiosity, what do you want to achieve by writing such code?
To be clear I dont understand exact need of this, But if there are only 3 cases, then you can encode them something like this,
void swapData(void* elem1, void* elem2, int type)
{
if( type == 0 ) //type == 0 corresponds to comparison of One & Two
{
One *e1 = (One*)elem1;
Two *e2 = (Two*)elem2;
int temp = e1->data;
e1->data = e2->data;
e2->data = temp;
}
else if(type == 1) //type == 1 corresponds to comparison of One & Three
{
One *e1 = (One*)elem1;
Three *e2 = (Three*)elem2;
int temp = e1->data;
e1->data = e2->data;
e2->data = temp;
}
else
{
//type == 2 corresponds to comparison of Two & Three
}
}
Call from the main function using third argument
swapData(&dog,&bird,0);
This method is not that efficient for higher cases
Create another data structure like this:
struct typee{
int ele1;
int ele2;
}id;
While filling elements:
id.ele1 = DOGS; // #define DOGS 1
id.ele2 = CATS; // #define CATS 2
Function definition:
void swapData(void* elem1, void* elem2, struct typee id) //<- addind new argument
{
//using id, type cast the ele1 and ele2 to theier structures
...
}
My suggestion:
typedef struct generic //only One structure at all
{
int data;
int specie;
}all;
main()
{
struct generic dog;
struct generic cat;
.... // filling structure elements
swapData(&dog, &cat);
...
}
Function definition:
void swapData(struct generic * elem1, struct generic* elem2)
{
int temp = elem1->data;
elem1->data = elem2->data;
elem2->data = temp;
}
There are several options available. Among them:
Switch to C++. You can then derive your three structs from a common base struct that includes the data member. Or use classes instead of structs and do the same thing. (This isn't as unhelpful as it might sound -- most C compilers these days also compile C++, and switching may be as simple as changing a file extension or compiler flag.)
Use a single struct containing a union for the second members. That way, you have only one type to deal with.
Use a single struct without the union and name the second member animals.
Create a struct Data that holds the data member, and then "piggyback" any other members onto that. That is, make sure that an instance of the Data struct is the very first member of One, Two, and Three. Then use type struct Data * when you only want to refer to the common part.
Look into ways to simulate OO-style polymorphism in C. Warning: it's not pretty.
Pass a pointer to the data member in each struct rather than a pointer to the entire struct.
Here's an example of that last strategy:
void swapData(int* data1, int* data2)
{
int temp = *data1;
*data1 = *data2;
*data2 = temp;
}
// call it like this:
swapData(&(dog->data), &(cat->data));
Any way you slice it, the swapData() function needs to know what it's dealing with. Plain old C doesn't provide inheritance polymorphism, so there's not a straightforward way to create a single base type that encompasses all three of your structs. So, you have to resort to passing just part of a struct, or casting the struct to a simpler type, etc. Since the data member is actually the first item in each of the structs, you can use the swapData() I provided above but simplify the call a little bit:
swapData((int*)dog, (int*)cat);
That's sneaky, though, and harder to understand (or maybe easier to misunderstand) even though it's shorter.

Resources