struct comparison

Badger BA 64810 bbadger at x102c.harris-atd.com
Fri Jul 21 00:59:53 AEST 1989


In article <2261 at auspex.auspex.com> you write:
>>Sure, you _may_ run into special cases, but is this any reason to leave out 
>>a useful operation?
>
>Well, it depends on how useful it *really* is; given enough "special
>cases", it may be that the only cases where it *is* useful are special
>cases, in which case you can whip up a macro to do the comparison.
>
>>Other languages, such as Ada (Oh no! The A-word!), provide for comparison
>>of composite objects (records in Ada correspond to structs in C).
>
>So how does Ada define comparison of records?
>From ANSI/MIL-STD-1815A 22 JAN 1983, which is sometimes called the Ada 
Language Reference Manual (ALRM), section 4.5.2:
\begin{quote}
[par 1] The equality and inequality operators are predefined for any type 
that is not limited. 
...
[par 5] For two array values or two record values of the same type,
the left operand is equal to the right operand if and only if 
for each component of the left operand there is a {\em matching component}
of the right operand, and vice versa; and the values of the matching 
components are equal, as given in the predefined equality operator for 
the component type. In particular, two null arrays of the same type are 
always equal; two null records of the same type are always equal.
[par 6] For comparing two records of the same type, {\em matching components}
are those which have the same component identifier.
\end{quote}

>
>>Of course there should be caveats about padding data being compared.
>
>I.e., "padding data gets compared"?  That doesn't sound like all that
>useful an operation to me; in order to be useful, I'd have to zero out
>structures on e.g. the stack.
>
Right, the component-by-component comparison is much safer, and is the 
natural approach for Ada.  Given C's low-level approach, though, I did 
not want to rule out from discussion a simplistic compare-all-bytes 
implementation.  That's also why I pointed out some gotcha's.

>>Also unions should only be compared to another union or object
>>which is *actually using* the same representation.  (That is, given:
>>	union lf_t {long l; float f} lf_a, lf_b;
>>	lf_a.l = 10; 
>>	lf_b.f = 10.0;
>>we should probably not be testing (lf_a == lf_b), but rather 
>>(lf_a.l == (long) lf_b.f).)
>
>Fine, so how is the compiler to know to do that?  C unions are not
>discriminated unions; there's nothing in the union itself to indicate
>which member is being used.
>
>>However, the fact remains that either simple ``compare all bytes'' or 
>>an expansion to compare all struct members recursively, would be a simple
>>extension which could be quite useful.
>
>Simple "compare all bytes" is certainly simple; how useful it is is
>another question, given that comparing padding bytes is simply wrong,
>unless you *guarantee* that they're always going to have some "standard"
>value that gets in the way.  You still haven't indicated how unions are
>to be compared, so an expansion to compare all struct members
>recursively would fail if any such members were unions.  And, once
>again, I'll point out that pointer comparison may or may not be what you
>want, either.
>
Yes, comparison of unions is not well-defined, so comparison of 
structs containing union members would also be not well-defined.

>In other words, comparison might be "simple" in a restricted sense, but
>nobody's proven that in that "simple" sense (i.e., bitwise comparison
>either of all the bits in the structure, or only the "meaningful" bits)
>this would be anywhere near "quite useful".
>
This goes a bit too far, because you throw out the useful comparisons with 
the ill-defined ones.  It is perfectly well-defined and quite handy 
to define a simple member-by-member comparison on structs and arrays.
The only thing you give up are the unions.  Comparison of pointers is 
defined to be comparison of the pointers themselves, just as always.
char *p, *q;
char a[] = "aa"; char b[] = "bb";
main(){
p = &a[0];q = &b[0];
strcpy(p,"hi"); strcpy(q,"hi"); 
if (p == p) {printf("Not in C you don't!\n");}
else printf("I thought that's what you meant!\n");
}

Now, I think that given:
	typedef struct _pt_t { int x,y,x; } pt_t, * pt_pt;
	typedef struct _pt_t polyline_t[3];
	pt_t p = { 11, 12, 13};
	pt_t q = {21, 22, 23};
	polyline_t pl = {{ 11, 12, 13}, { 21, 22, 23}, { 31, 32, 33}};
It would be nice to check things like:
	if ( pl[0] == p ) {}
rather than 
	if ( pl[0].x == p. &&  pl[0].y == p.y &&  pl[0].z == p.z ) {}


>If you want abstract data types, you know where to find them....
Well, this doesn't really have anything to do with abstraction, we're not 
hiding any implementation.  This is just structured data.  

I wouldn't cry either if a tagged-union record were added to C.  That would 
give the compiler a chance to do the union comparisons too, based on the 
tags.  

Bernard A. Badger Jr.	407/984-6385          |``Use the Source, Luke!''
Secure Computer Products                      |``Get a LIFE!''  -- J.H. Conway
Harris GISD, Melbourne, FL  32902             |Buddy, can you paradigm?
Internet: bbadger%x102c at trantor.harris-atd.com|'s/./&&/g' Tom sed expansively.



More information about the Comp.std.c mailing list