Si le champ ID que vous testez fait partie d'une séquence initiale commune de champs partagés par tous struct, puis à l'aide d'un syndicat garantit que l'accès fonctionne:
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int id;
long junk2;
} Bar;
typedef union
{
struct
{
int id;
} common;
Foo foo;
Bar bar;
} U;
int matches(const U *candidate, int wanted)
{
return candidate->common.id == wanted;
}
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 42, 0 };
U fu;
U bu;
fu.foo = f;
bu.bar = b;
puts(matches(&fu, 23) ? "true" : "false");
puts(matches(&bu, 42) ? "true" : "false");
return 0;
}
Si vous êtes malchanceux, et le champ apparaît à différents décalages dans les différents struct, vous pouvez ajouter un paramètre de décalage à votre fonction. Ensuite, offsetof et une macro d'encapsulation simulent ce que l'OP a demandé - en passant le type de struct sur le site d'appel:
#include <stddef.h>
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int junk2;
int id;
} Bar;
int matches(const void* candidate, size_t idOffset, int wanted)
{
return *(int*)((const unsigned char*)candidate + idOffset) == wanted;
}
#define MATCHES(type, candidate, wanted) matches(candidate, offsetof(type, id), wanted)
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 0, 42 };
puts(MATCHES(Foo, &f, 23) ? "true" : "false");
puts(MATCHES(Bar, &b, 42) ? "true" : "false");
return 0;
}
Il n'y a aucun moyen que cela compile jamais. Vous ne pouvez pas déréférencer un pointeur pour annuler comme ça. –
Eh bien, pour être juste, j'ai dit que j'étais rouillé en C.;) –