[comp.std.c] Re^2: struct comparison

maart@cs.vu.nl (Maarten Litmaath) (07/15/89)

henry@utzoo.uucp (Henry Spencer) writes:
\In article <2874@solo3.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
\>Why does the PROGRAMMER have to go through all that trouble?
\>I just want to say:
\>
\>	puts(mork == mindy ? "equal" : "unequal");
\>
\>Is the ANSI committee trying to tell us the compiler cannot transform the
\>equality test into the correct member-by-member comparison code?
\
\Yes.  Think about unions.  Or pointers (do you compare the pointers or
\what they point at?).  The compiler just doesn't have enough information.

I thought of those as well:
1)	pointers - They should be compared themselves; if they don't point to
	the same location, they're unequal by definition; if the data they
	point at are equal, that's mere coincidence.
2)	unions - Compare with the following example:

		struct	foo {
				char	bar[10];
			} x, y;
		
		(void) strcpy(x.bar, "123456789");
		(void) strcpy(y.bar, "987654321");
		(void) strcpy(x.bar, "zork");
		(void) strcpy(y.bar, "zork");

		puts(x == y ? "yes" : "no");

	I say the output should be "no", because all 10 bytes in `bar' must
	be compared. (The array needn't be a string at all! I might have used
	it to store small integers.)
	If you want to get "yes", you have to make sure there's no garbage
	at the end of `bar', i.e. you must clear the unused part explicitly.
	Unions can be dealt with likewise.

I KNOW these two specifications might cause some surprises in actual code,
but:
1)	Compare with this little gem to confuse Pascal programmers:

		if ("string" != "string")
			puts("how weird!");

2)	The following example shows how useful struct comparison could be:

		struct	complex {
				int	real;
				int	imag;
			} z, w;

		...
		if (z == w) ...
-- 
   "... a lap-top Cray-2 with builtin    |Maarten Litmaath @ VU Amsterdam:
cold fusion power supply"  (Colin Dente) |maart@cs.vu.nl, mcvax!botter!maart

henry@utzoo.uucp (Henry Spencer) (07/16/89)

In article <2878@kappl.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>\Yes.  Think about unions.  Or pointers (do you compare the pointers or
>\what they point at?).  The compiler just doesn't have enough information.
>
>I thought of those as well:
>1)	pointers - They should be compared themselves; if they don't point to
>	the same location, they're unequal by definition; if the data they
>	point at are equal, that's mere coincidence.

For "char *" in particular, comparing the pointers themselves usually
won't be what's wanted.  Of course, if the compiler wants to try to
compare the chars, then it has to know whether the pointers really point
to strings... and it doesn't.  Same problem with char arrays inside a
struct -- is that a string (i.e. stuff past the NUL doesn't count) or not?

>	If you want to get "yes", you have to make sure there's no garbage
>	at the end of `bar', i.e. you must clear the unused part explicitly.
>	Unions can be dealt with likewise.

How?  There *isn't* any (reliable) way to get at the unused part.  You
could assign the same constant to the longest member in each union --
but in general you don't know which member *is* longest.

Oh sure, these things can be dealt with... but every time you deal with
one, you reduce the utility of the feature by placing more and more
restrictions on how it can be used and what answers it gives.  It's not
worth it.

>1)	Compare with this little gem to confuse Pascal programmers:
>
>		if ("string" != "string")
>			puts("how weird!");

Actually the answer to this one is implementation-defined, to make things
still weirder.  ANSI C can combine string literals.  But consider, say,
"if a<b and c<d then ..." in Pascal -- guaranteed to surprise a C programmer.
This sort of cross-language comparison is silly; all it proves is that most
languages have surprises for the unwary, and treating C as it were Pascal --
or vice versa -- is foolish.

>2)	The following example shows how useful struct comparison could be:
>		struct	complex {
>				int	real;
>				int	imag;
>			} z, w;
>		if (z == w) ...

Sigh, this one is pretty standard.  It's also dumb; do you then want to
define struct add and subtract as well?  It's also not a particularly good
idea:  suppose I change to a polar form, where the representation of a given
complex number is not unique?  The right answer to this one is C++, where
you can *define* what the operators mean.

To quote Dennis Ritchie:  "if you want PL/I, you know where to find it".
-- 
$10 million equals 18 PM       |     Henry Spencer at U of Toronto Zoology
(Pentagon-Minutes). -Tom Neff  | uunet!attcan!utzoo!henry henry@zoo.toronto.edu