One approach would be to use the C Preprocessor if you have a dependency on the struct
members.
However based on your comment you really have only a single dependency on the struct
type and members which is the assignment which is done in a particular place.
The easiest thing would be to use the suggestion from Leonardo Herrera in the comment above and pass in the struct
size and then use memcpy()
with the size of the struct
argument.
Another possibility is to create two functions, one which does the work before the assignment and a second which does the work after the assignment and then call the first function, do the actual assignment, and then call the second function. For instance:
// define the structs that we are using.
typedef struct {
int jj;
int kk;
} s1;
typedef struct {
int kk;
int ii;
int jj;
} s2;
// define the function that does the first part of the work
void PhaseOne (/* arg list */)
{
// phase one of the functionality
}
// define the function that does the second part of the work
void PhaseTwo (/* arg list */)
{
// phase two of the functionality
}
myFunctionUser (void)
{
s1 a1, b1;
s2 a2, b2;
// do things with a1 and b1 in prep to call the function
// do things with a2 and b2 in prep to call the function
PhaseOne (/* arg list */);
a1 = b1;
PhaseTwo (/* arg list */);
PhaseOne (/* arg list */);
a2 = b2;
PhaseTwo (/* arg list */);
// do more stuff
}
If there is need for state to be communicated between PhaseOne()
and PhaseTwo()
or if there is some change needed to the variables which are being assigned based on the state from PhaseOne()
or PhaseTwo()
then you might need to have a struct
or other variable type for that.
However another thing would be to write a function that takes a pointer to another function and in the other function do the assignment. This is borrowing the idea of how the C Standard Library uses a comparison function with the qsort()
function. And using this approach if there are additional things to do with the structs besides the assignment then the function pointed to would be the place to do it since at that point you can do a cast to the appropriate type and then do whatever.
// define the structs that we are using.
typedef struct {
int jj;
int kk;
} s1;
typedef struct {
int kk;
int ii;
int jj;
} s2;
void AssignS1 (void *a, void *b) { *((s1 *)a) = *((s1 *)b); return; }
void AssignS2 (void *a, void *b) { *((s2 *)a) = *((s2 *)b); return; }
void myFunction (void *a, void *b, void (*pFunc)(void *x, void *y))
{
// do stuff
pFunc(a, b); // do the assignment
// do more and more and tons of stuff
}
myFunctionUser (void)
{
s1 a1, b1;
s2 a2, b2;
// do things with a1 and b1 in prep to call the function
// do things with a2 and b2 in prep to call the function
myFunction (&a1, &b1, AssignS1);
myFunction (&a2, &b2, AssignS2);
// do more stuff
}
Just for grins here is an approach using the C Preprocessor to generate source based on a particular struct type. It is quite ugly and difficult for debugging and requires some degree of discipline on the part of the programmer. This is a small and simple function to illustrate the procedure and I guarantee you that it will not scale well.
// define a macro that will generate various type specific versions of a function.
#define WriteThing(s) void WriteThing##s (s *a, s *b) \
{ *a = *b; if (a->jj != 4) { a->jj += b->jj + 10;} return; }
// define the function we will use to call the above function based on the type of the arguments
#define WriteThingCall(s,a,b) WriteThing##s (a, b)
// define the structs that we are using.
typedef struct {
int jj;
int kk;
} s1;
typedef struct {
int kk;
int ii;
int jj;
} s2;
// generate the functions we are going to need for our different types
WriteThing(s1)
WriteThing(s2)
// example function of how to use this approach.
void func (void)
{
s1 a1 = {0}, b1 = {0};
s2 a2 = {0}, b2 = {0};
WriteThingCall(s1, &a1, &b1);
WriteThingCall(s2, &a2, &b2);
}