[BusyBox] compare structs without comparing all the fields ?

Manuel Novoa III mjn3 at codepoet.org
Sat Apr 20 15:17:03 UTC 2002


Glen,

On Sun, Apr 21, 2002 at 03:28:45AM +1000, Firewall wrote:
> Is it possible to compare two structs without comparing all their fields ?

Only if there are no holes.

> #define BITWIDTH_REVISION 9
> typedef struct package_version_s {
> 	unsigned short package:14;
> 	unsigned short epoch:4;
> 	unsigned short upstream:12;
> 	unsigned short revision:BITWIDTH_REVISION;
> } __attribute__ ((__packed__)) package_version_t;
> 
> Im trying to use the memcmp statement below to compare two variable of the
> above type but the results arent always correct, i.e. there are cases
> where the two variables fields have the same contents, but they arent
> considered equal acording to memcmp.
> 
> if (memcmp(package_version, package_version_key,
> sizeof(package_version_t)) == 0) {

Since you have some excess uninitialized bits, you shouldn't expect the
above to work.  Now, if we assume that CHAR_BIT==8 and the compiler
honors the packed attribute and sizeof(package_version_t)==5, then
you could do the following and expect your memcmp test to work.

typedef struct package_version_s {
	unsigned short epoch:4;
	unsigned short upstream:12;
#if BITWIDTH_REVISION == 9
	unsigned short package:15;
#elif BITWIDTH_REVISION == 8
	unsigned short package:16;
#else
#error unexpedted BITWIDTH_REVISION
#endif
	unsigned short revision:BITWIDTH_REVISION
} __attribute__ ((__packed__)) package_version_t;

In the above, I moved package for (hopefully -- depending on the 
compiler and on arch endianess) more efficient alignment
of the fields.  Also, depending on what value you wanted to use for
BITWIDTH_REVISION, I added a bit or two for padding to the package
field so that all bits in bytes used are accounted for.  This has
the advantage of not forcing you to initialize some extra padding
field.  Try playing with the code attached below.

Manuel

#include <stdio.h>
#include <limits.h>

#define BITWIDTH_REVISION 8

#if 0

/* Original layout */
#define BITWIDTH_PACKAGE 14
typedef struct package_version_s {
	unsigned short package:BITWIDTH_PACKAGE;
	unsigned short epoch:4;
	unsigned short upstream:12;
	unsigned short revision:BITWIDTH_REVISION;
} __attribute__ ((__packed__)) package_version_t;

#else

#if BITWIDTH_REVISION == 9
#define BITWIDTH_PACKAGE 15
#elif BITWIDTH_REVISION == 8
#define BITWIDTH_PACKAGE 16
#else
#error unexpedted BITWIDTH_REVISION
#endif

typedef struct package_version_s {
	unsigned short epoch:4;
	unsigned short upstream:12;
	unsigned short package:15;
	unsigned short package:BITWIDTH_PACKAGE;
	unsigned short revision:BITWIDTH_REVISION;
} __attribute__ ((__packed__)) package_version_t;

#endif


static int field_span(unsigned long long ull)
{
	unsigned long long b;

	b = (1ULL << (CHAR_BIT*sizeof(long long) - 1));
	do {
		putchar("01"[!!(ull & b)]);
		b >>= 1;
	} while (b);
	putchar('\n');
}

int main(void)
{
	union {
		unsigned long long ull;
		package_version_t pv;
	} u;
	int i;

	printf("sizeof(package_version_t) == %d\n", sizeof(package_version_t));

	for (i=0 ; i < CHAR_BIT*sizeof(long long) ; i++) {
		putchar( ((i & 7) == 7) ? '+' : ' ' ); /* mark bit 0 on bytes */
	}
	putchar('\n');

	u.ull = 0;
	u.pv.package = (1<<BITWIDTH_PACKAGE)-1;
	field_span(u.ull);

	u.ull = 0;
	u.pv.epoch = (1<<4)-1;
	field_span(u.ull);

	u.ull = 0;
	u.pv.upstream = (1<<12)-1;
	field_span(u.ull);

	u.ull = 0;
	u.pv.revision = (1<<BITWIDTH_REVISION)-1;
	field_span(u.ull);

	return 0;
}



More information about the busybox mailing list