comparing two structures

J

junky_fellow

Guys,

Is it a good way to compare two structures for equality by using
"memcmp" ?

If not, what could be the problems associated with this ? And what is
the correct
method of doing this ?

thanks for any help.
 
R

Richard Heathfield

(e-mail address removed) said:
Guys,

Is it a good way to compare two structures for equality by using
"memcmp" ?
No.

If not, what could be the problems associated with this ?

Padding bytes, and dynamically allocated memory pointed to by struct
members.
And what is the correct method of doing this ?

int cmp(const struct T *a, const struct T *b);
 
C

CBFalconer

Richard said:
(e-mail address removed) said:


Padding bytes, and dynamically allocated memory pointed to by
struct members.


int cmp(const struct T *a, const struct T *b);

Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Which means you have to write a cmp() each structure type. You may
have to resolve embedded pointers.
 
R

Richard Heathfield

CBFalconer said:
Richard Heathfield wrote:


Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Personally, I would find a relational comparison more generally useful.

<snip>
 
J

John Gordon

In said:
Is it a good way to compare two structures for equality by using
"memcmp" ?
No.

If not, what could be the problems associated with this?

One such problem is comparison of strings. The contents of a string are
meaningless after the terminating null byte, but memcmp() wouldn't know
that.
 
T

Tor Rustad

CBFalconer wrote:

[...]
Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Which means you have to write a cmp() each structure type. You may
have to resolve embedded pointers.

Very confusing name choice, unless cmp() return 0 if equal.
 
C

CBFalconer

Richard said:
CBFalconer said:

Personally, I would find a relational comparison more generally
useful.

Granted, but generally impossible. For:

struct foobar {int foo; char bar);

please define a suitable cmp function that is relational, without
somehow defining the relative importance of foo and bar. :) I'm
sure you know this, but the comment is for general consumption.
 
R

Richard Heathfield

CBFalconer said:
Richard Heathfield wrote:

Granted, but generally impossible.

Generally, yes, but specifically, no. The problem domain expert will be
able to specify the ordering between two objects of the same structure
type (and possibly several orderings, in which case several functions
can be written).
 
C

CBFalconer

Tor said:
CBFalconer wrote:

[...]
Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Which means you have to write a cmp() each structure type. You
may have to resolve embedded pointers.

Very confusing name choice, unless cmp() return 0 if equal.

You have my full permission to interchange 0 and 1. :)
 
T

Tor Rustad

CBFalconer said:
Tor said:
CBFalconer wrote:

[...]
Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Which means you have to write a cmp() each structure type. You
may have to resolve embedded pointers.
Very confusing name choice, unless cmp() return 0 if equal.

You have my full permission to interchange 0 and 1. :)

The API is still broken to my mind. :)

If first argument is less, then cmp() should return negative (e.g. -1),
if first argument is greater, then cmp() should return positive (e.g. 1).


Furthermore, if writing a cmp() function, I rather prefer to use the
same interface and return value as qsort() and bsearch() expect:

int cmp_mystruct(const void *, const void *)

why compare "struct's", unless doing sorting and searching?
 
R

Richard Heathfield

Tor Rustad said:

Furthermore, if writing a cmp() function, I rather prefer to use the
same interface and return value as qsort() and bsearch() expect:

int cmp_mystruct(const void *, const void *)

why compare "struct's", unless doing sorting and searching?

Well said, although I think I'd like to add an extra void * to that, so
that the comparison function can use (or provide) additional
information about the comparison without resorting to global data.
This, of course, requires ISO to change the spec for qsort and bsearch,
or provide sensibly-designed versions thereof.

Jump to it, lads...
 
P

pete

Tor Rustad wrote:
Furthermore, if writing a cmp() function, I rather prefer to use the
same interface and return value as qsort() and bsearch() expect:

int cmp_mystruct(const void *, const void *)

why compare "struct's", unless doing sorting and searching?

If you had a linked list of structures
and if you had a list sorting function that
took a compar function pointer as an argument,
then it would make more sense to have pointers to the list node type.
 
C

CBFalconer

Tor said:
CBFalconer said:
Tor said:
CBFalconer wrote:

[...]

Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Which means you have to write a cmp() each structure type.
You may have to resolve embedded pointers.

Very confusing name choice, unless cmp() return 0 if equal.

You have my full permission to interchange 0 and 1. :)

The API is still broken to my mind. :)

If first argument is less, then cmp() should return negative
(e.g. -1), if first argument is greater, then cmp() should
return positive (e.g. 1).

But you are dealing with a struct. How do you define 'less' when
there are multiple components, with no less/greater definition.
Furthermore, if writing a cmp() function, I rather prefer to use
the same interface and return value as qsort() and bsearch()
expect:

int cmp_mystruct(const void *, const void *)

why compare "struct's", unless doing sorting and searching?

No, you can compare some fields of structs, but not complete
structs, for relative magnitude. The problem handled by void* is
not within the cmp function, but within the caller, who may not
need to know anything more than the cmp result about the struct.
The definition of cmp is up to you.
 
R

Richard Heathfield

CBFalconer said:

But you are dealing with a struct. How do you define 'less' when
there are multiple components, with no less/greater definition.

It depends on the domain. You are right that there is no general
solution, but that does not mean that there are no domain-specific
solutions. Nor does it mean that you cannot have multiple comparison
functions for the same type.

The definition of cmp is up to you.

Precisely.
 
T

Tor Rustad

CBFalconer said:
Tor said:
CBFalconer said:
Tor Rustad wrote:
CBFalconer wrote:

[...]

Which should resolve to (very roughly}:

for (c = eachcomponentof a) {
if ((a->c) != (b->c)) return 0; /* unequal */
}
return 1; /* i.e. structures equal */

Which means you have to write a cmp() each structure type.
You may have to resolve embedded pointers.
Very confusing name choice, unless cmp() return 0 if equal.
You have my full permission to interchange 0 and 1. :)
The API is still broken to my mind. :)

If first argument is less, then cmp() should return negative
(e.g. -1), if first argument is greater, then cmp() should
return positive (e.g. 1).

But you are dealing with a struct. How do you define 'less' when
there are multiple components, with no less/greater definition.

Hmmm.. what does this "comparing struct" mean?

Normally, when comparing ADT, the ADT has a key defined, e.g. like this:

struct node
{
KEY_T id;
DATA_T data;
};

and you only compare the key, not *all* the members of the struct.

When a programmer name a function cmp(), I expect a compare operation to
be defined. If only testing for equality, a far better name choice would
be e.g. 'is_equal()'.

See return value of memcmp, strcmp, ... it's <0, 0 or >0.
 
T

Tor Rustad

pete said:
If you had a linked list of structures
and if you had a list sorting function that
took a compar function pointer as an argument,
then it would make more sense to have pointers to the list node type.

Agreed, in this case, I wouldn't use void*, but rather

int is_equal(KEY_T, KEY_T );
int is_less (KEY_T, KEY_T );
 
T

Tor Rustad

Richard said:
CBFalconer said:
[...]
The definition of cmp is up to you.

Precisely.

The compiler doesn't mind bad identifiers, but humans do...

The point is that the standard C library, the *is* functions return
differently, than the *cmp* functions do.


So, if you are consistent, you can't object to code with:

int is_zero(int c)
{
return ('0' != c);
}

either.
 
R

Richard Heathfield

Tor Rustad said:
Richard said:
CBFalconer said:
[...]
The definition of cmp is up to you.

Precisely.

The compiler doesn't mind bad identifiers, but humans do...

The point is that the standard C library, the *is* functions return
differently, than the *cmp* functions do.


So, if you are consistent, you can't object to code with:

int is_zero(int c)
{
return ('0' != c);
}

either.


You lost me. Remember that my preference is for relational comparison, a
la strcmp and memcmp, rather than for equality-only comparison.

If you realised this and still think you have a point, I'd be curious to
know what that point is.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,190
Latest member
ClayE7480

Latest Threads

Top