Not sure if the title is suggestive enough but here's what I'm trying to do.
Let's say I have some code that I won't touch, basically let's say a function that fills in a structure.
Now that structure is defined somewhere else and I found it easy not to drag the whole thing into the project and just copying the struct definition would be an overkill.
So I defined a new struct with only开发者_运维问答 the relevant fields and I'm trying to send it to the function so that it would be filled up with the relevant fields.
typedef struct {
......
} mytype;
The function header:
int function_header (struct type1 *p, ....);
Keep in mind struct type1 is not defined anywhere. Is there a way to abuse the preprocessor to get something like?
#define (struct type1) mytype
One solution would be I guess
#define type1 mytype
#define struct
int function_header (struct type1 *p, ....) {
#undef struct
..............
}
But seems a bit retarded
Why do you want to rename it? Just define
struct type1 {
...
};
in your own source file, and you're all set to go a-footshooting. (And remember, feet will be hurt unless you're 100% sure that your own definition leads to exactly the same in-memory layout as the one expected by the library).
First of all, be careful. You cannot arbitrarily remove fields from the original struct
and expect the function to "fill them in". You can define a compatible struct
of your own making, but it must contain the exact same fields in the exact same order, or very bad things can happen. You can then send an instance of this structure with uninitialized field values to the function, and it will set values into your fields as it normally would. But you cannot remove a field and then expect the function to add it back.
Of course, even if you define an exact copy of the struct
, you're risking all sorts of issues, as if someone changes the other struct
without updating your version, things will break. Similarly things will break if your declaration is updated without a corresponding update made to the original struct
. It would be far better to just move the definition of the original struct
to a shared header file that can be included in all the places that need to use that struct
. Then there's just one definition that everyone uses.
But anyways, as your function is just expecting a pointer to the structure, you can call it with pretty much anything you want. Just cast your parameter to void*
, as shown here:
http://ideone.com/c4qtT
Of course, as noted above, this will only work correctly if the pointer that you are casting is pointing to something that has an in-memory layout exactly identical to the original struct
.
You can define your new structure having the original structure as its first member. Example:
struct mytype {
struct type1 original;
int custom_field;
};
Since the ISO says there will be no padding before the first member of a struct
, if you have a struct mytype*
, it allows you to cast it to struct type1*
without undefined behavior.
However, you'll get into trouble if the original code uses sizeof
to traverse an array of struct type1
instances, whereas the original array is in fact of struct mytype
instances.
No, you can't do that. The external function doesn't "know" about any defines, redefines, redeclarations, etc. If you make your struct smaller, there is a chance that the function, thinking it is writing to the original struct, writes across the boundaries of your smaller struct.
Don't do this, unless you really really really know what you are doing.
From what I understood you don't want to change the header file, but you have full access to the source file?
You wrote:
#define type1 mytype
#define struct
int function_header (struct type1 *p, ....) {
#undef struct
..............
}
it seems you can easily modify the function body. Why don't you just manually change all the struct type1 references to mytype? It's just a simple find&replace in text editor... The thing that preprocessor would do is just the same, it replaces all the occurrences of one text with another.
精彩评论