So che memcmp()
non può essere utilizzato per confrontare le strutture che non sono state memset()
a 0 a causa del riempimento non inizializzato. Tuttavia, nel mio programma ho una struttura con alcuni tipi diversi all'inizio, quindi diverse dozzine dello stesso tipo fino alla fine della struttura. Il mio pensiero è stato quello di confrontare manualmente i primi tipi, quindi utilizzare uno memcmp()
sul blocco di memoria contigua rimanente degli stessi membri digitati.Confrontare le strutture in C utilizzando memcmp() e aritmetica del puntatore
La mia domanda è: cosa garantisce lo standard C per il riempimento della struttura? Posso ottenerlo in modo affidabile su qualsiasi o tutti i compilatori? Lo standard C consente l'inserimento di struct padding tra membri dello stesso tipo?
Ho implementato il mio soluzione proposta, e sembra funzionare esattamente come previsto con gcc
:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct foo
{
char a;
void *b;
int c;
int d;
int e;
int f;
};
static void create_struct(struct foo *p)
{
p->a = 'a';
p->b = NULL;
p->c = 1;
p->d = 2;
p->e = 3;
p->f = 4;
}
static int compare(struct foo *p1, struct foo *p2)
{
if (p1->a != p2->a)
return 1;
if (p1->b != p2->b)
return 1;
return
/* Note the typecasts to char * so we don't get a size in ints. */
memcmp(
/* A pointer to the start of the same type members. */
&(p1->c),
&(p2->c),
/* A pointer to the start of the last element to be compared. */
(char *)&(p2->f)
/* Plus its size to compare until the end of the last element. */
+sizeof(p2->f)
/* Minus the first element, so only c..f are compared. */
-(char *)&(p2->c)
) != 0;
}
int main(int argc, char **argv)
{
struct foo *p1, *p2;
int ret;
/* The loop is to ensure there isn't a fluke with uninitialized padding
* being the same.
*/
do
{
p1 = malloc(sizeof(struct foo));
p2 = malloc(sizeof(struct foo));
create_struct(p1);
create_struct(p2);
ret = compare(p1, p2);
free(p1);
free(p2);
if (ret)
puts("no match");
else
puts("match");
}
while (!ret);
return 0;
}
Minore: Poiché i puntatori confrontati restituiscono 0 o 1, suggerendo di assicurare 'memcmp() 'restituisce 0 o 1 con' memcmp()! = 0'. – chux
@chux Buona idea, grazie per il suggerimento. – John