は、初期化されていないパディングのためにmemset()
にない構造体を比較するために使用できません。しかし、私のプログラムでは、始めにいくつかの異なるタイプの構造体があり、構造体の終わりまで同じタイプの構造体が数十個あります。最初のいくつかの型を手動で比較し、同じ型付きメンバの残りの連続したメモリブロックにmemcmp()
を使用することを考えました。memcmp()とポインタ算術を使ってCの構造体を比較する
私の質問は、C標準が構造体の埋め込みについて何を保証していますか?すべてのコンパイラで確実にこれを達成できますか? C標準では、同じタイプのメンバー間で構造体のパディングを挿入できますか?
私は提案されたソリューションを実装している、そしてそれは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;
}
マイナー:あなたのポインタ比較が0か1を返すので、 'memcmp()'が 'memcmp()!= 0'で0または1を返すようにしてください。 – chux
@chux良いアイデア、提案のおかげで。 – John