Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

struct comparison

8 views
Skip to first unread message

Maarten Litmaath

unread,
Jul 13, 1989, 6:34:39 PM7/13/89
to
According to the pANS structs can be

- assigned
- returned
- used as function arguments

but they cannot be COMPARED, right? Very annoying.
The reason appears to be internal padding, whose contents aren't specified.
Thus the following won't work:

struct foo {
char bar;
int baz;
double zork;
} mork, mindy;

...
puts(bcmp((char *) &mork, (char *) &mindy, sizeof mork) == 0 ?
"equal" : "unequal");

To compare the 2 structs, one now has to check each field oneself:

puts(mork.bar == mindy.bar && mork.baz == mindy.baz
&& mork.zork == mindy.zork ? "equal" : "unequal");

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?
--
"... a lap-top Cray-2 with builtin |Maarten Litmaath @ VU Amsterdam:
cold fusion power supply" (Colin Dente) |ma...@cs.vu.nl, mcvax!botter!maart

Henry Spencer

unread,
Jul 14, 1989, 11:53:12 AM7/14/89
to
In article <28...@solo3.cs.vu.nl> ma...@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.
--
$10 million equals 18 PM | Henry Spencer at U of Toronto Zoology
(Pentagon-Minutes). -Tom Neff | uunet!attcan!utzoo!henry he...@zoo.toronto.edu

Maarten Litmaath

unread,
Jul 14, 1989, 8:30:41 PM7/14/89
to
he...@utzoo.uucp (Henry Spencer) writes:

\In article <28...@solo3.cs.vu.nl> ma...@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) ...

Doug Gwyn

unread,
Jul 15, 1989, 1:22:55 AM7/15/89
to
In article <28...@solo3.cs.vu.nl> ma...@cs.vu.nl (Maarten Litmaath) writes:
>Is the ANSI committee trying to tell us the compiler cannot transform the
>equality test into the correct member-by-member comparison code?

No, but apart from the padding issue it is not clear what would
constitute "equality" in practice; memberwise comparison would
seldom be what one really wanted. Consider char* members, for
example; probably struct equality in such a case should use the
equivalent of strcmp() on those members. Floating-point equality
tests are usually meaningless (except sometimes when one of the
operands is precisely zero). Union members pose yet another
problem. And so on. Given such pratical problems, and that a
programmer can perform this test another way, and that it would
be an "invention", X3J11 chose not to require support for
aggregate equality testing.

There were an immense number of suggestions for such linguistic
enhancements received by X3J11, as listed in the introduction to
each official public review response document. If there is much
interest, I could post the list in order to give you a better
appreciation of why such suggestions were routinely rejected.

Niels J|rgen Kruse

unread,
Jul 15, 1989, 11:10:30 AM7/15/89
to
he...@utzoo.uucp (Henry Spencer) writes:

>In article <28...@solo3.cs.vu.nl> ma...@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.

Just like the compiler doesn't have enough information to
initialize a union, right? !

A simple rule like comparing first members of unions and the
pointers themselves would work nicely in a lot of cases and
match the way initialization works.

Or comparison of structs with inconvenient members could just
be outlawed, which wouldn't reduce the usefullness much.

Or perhaps better, inconvenient members could just be ignored,
leaving them for the programmer to handle separately.
--
Niels J|rgen Kruse
Email n...@diku.dk
Mail Tustrupvej 7, 2 tv, 2720 Vanlose, Denmark

Henry Spencer

unread,
Jul 15, 1989, 5:08:21 PM7/15/89
to
In article <28...@kappl.cs.vu.nl> ma...@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".

R. Vuurboom

unread,
Jul 17, 1989, 2:17:03 PM7/17/89
to
In article <1989Jul15....@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
>
>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?
>
I might agree with your conclusion but I'm not too happy with your arguments.
Why should struct comparison be also supported for those structs with
member objects for which direct comparison support is not provided (arrays
and strings case in point - your example).

Now _if_ I were to define struct comparison it would _only_ be for
structs for which each member can be directly compared or
is a struct to which this requirement is recursively applied.
Something a compiler could figure out pretty easily in my opinion.
If you perchance attempt to compare two structs that don't satisfy above
the compiler could always bark at you.
(Mind you, I only said _if_ :-)

I agree with Doug Gwyn though. Defining this would have been extending
the language and not just standardizing it. Perhaps Doug should go
ahead and post that list of arguments.

>Sigh, this one is pretty standard. It's also dumb; do you then want to
>define struct add and subtract as well?

Then he would have said so wouldn't he :-)

>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?

Henry, this is cheating :-). If somebody comes along and changes the
representation of an int while I'm not looking nobody expects the
two values (old representation vs new representation) to compare equal.

>
>To quote Dennis Ritchie: "if you want PL/I, you know where to find it".

Where the sun don't shine? :-)
--
Its a thin red line between boring and borish.

Roelof Vuurboom SSP/V3 Philips TDS Apeldoorn, The Netherlands +31 55 432226
domain: roe...@idca.tds.philips.nl uucp: ...!mcvax!philapd!roelof

Henry Spencer

unread,
Jul 17, 1989, 10:04:24 PM7/17/89
to
In article <1...@ssp1.idca.tds.philips.nl> roe...@idca.tds.PHILIPS.nl (R. Vuurboom) writes:
>>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?
>
>Henry, this is cheating :-). If somebody comes along and changes the
>representation of an int while I'm not looking nobody expects the
>two values (old representation vs new representation) to compare equal.

Not quite what I was getting at. The point of polar representation is
that member-by-member comparison does not dependably get the right answer!
Equality comparison on polar representation requires range reduction on
the angle first. This leads again to the need for C++, where you can
define the comparison operation to be arbitrarily complex.

Badger BA 64810

unread,
Jul 18, 1989, 9:58:26 AM7/18/89
to

Sure, you _may_ run into special cases, but is this any reason to leave out
a useful operation? Other languages, such as Ada (Oh no! The A-word!),
provide for comparison of composite objects (records in Ada correspond to
structs in C). Of course there should be caveats about padding data being
compared. 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).)

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.

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%x1...@trantor.harris-atd.com|'s/./&&/g' Tom sed expansively.

R. Vuurboom

unread,
Jul 18, 1989, 11:32:16 AM7/18/89
to
In article <1989Jul18....@utzoo.uucp| he...@utzoo.uucp (Henry Spencer) writes:
|
|Not quite what I was getting at. The point of polar representation is
|that member-by-member comparison does not dependably get the right answer!
|Equality comparison on polar representation requires range reduction on
|the angle first. This leads again to the need for C++, where you can
|define the comparison operation to be arbitrarily complex.

No need to be arbitrary...polar or rectangular will do nicely :-)
--
Its a thin red line (and spelling error) between boring and borish.

Norman Diamond

unread,
Jul 18, 1989, 10:19:07 PM7/18/89
to

>Why should struct comparison be also supported for those structs with
>member objects for which direct comparison support is not provided (arrays

>and strings case in point - [Henry Spencer's] example).

Maybe for the same reason structs can be passed as function parameters
and be returned as results even when some member objects do not have
direct assignment support (arrays and strings for example).

C-90 (maybe C-89 if they're quick) did define a lot more new practices
than is admitted by Doug Gwyn. C-0x will define many more. C-0x will
be called C, not D; just as C-90 is still called C. So this newsgroup
is in fact an appropriate place for this kind of discussion.

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.s...@relay.cs.net)
The above opinions are inherited by your machine's init process (pid 1),
after being disowned and orphaned. However, if you see this at Waterloo or
Anterior, then their administrators must have approved of these opinions.

Guy Harris

unread,
Jul 19, 1989, 7:10:09 PM7/19/89
to
>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?

>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.

>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.

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".

If you want abstract data types, you know where to find them....

Norman Diamond

unread,
Jul 19, 1989, 8:00:38 PM7/19/89
to
In article <1989Jul18....@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:

>Equality comparison on polar representation requires range reduction on
>the angle first. This leads again to the need for C++, where you can
>define the comparison operation to be arbitrarily complex.

Well, with ordinary integers, overflow might occur. Does this mean that
"+" should not be provided for integers?

--

Badger BA 64810

unread,
Jul 20, 1989, 10:59:53 AM7/20/89
to
In article <22...@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.

R. Vuurboom

unread,
Jul 20, 1989, 1:08:39 PM7/20/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
>
>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.

Whipping, as is well known, is unpleasant at best (but may depend on
which side of the whip you're on :-)


>>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.

Agree.

>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.

Don't we all love to point out the obvious: a struct is not a union and
a union is not a struct and never the twain shall meet.

To repeat a struct comparison definition I posted a few days back:

Now _if_ I were to define struct comparison it would _only_ be for
structs for which each member can be directly compared or
is a struct to which this requirement is recursively applied.

This (and the above) definition is strictly Thatcherite: _no_ unions.

With this definition we've got the corollary that two structs compare
equal if and only if their members compare equal.

So I disallow struct comparisons with structs which have unions,
arrays and bitfields as members and possibly some other cases which
I can't think of but others undoubtedly can. But my point is that
I've still got an awful lot of structs *which occur in the real world*
for which I can (and several times wished I could) do a sensible comparison.

Looking at the arguments up to now that have been advanced against
struct comparison:

1. unions, bit fields (and the related case of data padding)

Agreed. But my argument above is that if I exclude these cases I've
still got a very relevant operation.


2. member arrays, strings.

Why demand direct language support for comparison of arrays/strings in
a struct if you don't do it directly? Again exclude this case: I've
still got a useful, relevant comparison operator.

3. polar complex example

It took a while before I began to get the sneaky feeling that maybe
Henry Spencer had put one over me here.

His argument was that because a certain _mathematical_ concept (complex
comparison) couldn't be supported this was (one of the) grounds for
omitting a _language_ concept (struct comparison).

This argument holds in my opinion as much water as defining the
concept angle as:

typedef int angle;

Stating that angles modulo 360 are really equal and then stating that
since angle1 and angle2 don't compare equal (even when separated by
360 degrees) somethings wrong with the (int) comparison operation
(and perhaps should be omitted :-).

4. Language Extension

(I've changed my mind on this one). It extends the language but not (much)
more than say returning a struct does and less in my opinion than function
prototyping for example.

5. The comparison is not simple.

Agreed if you want to be able to compare all possible structs. Disagree
if you restrict to the above definition. In that case, struct comparison
is relatively easily to implement, it certainly is easy to
comprehend and it most certainly is a relevant, useful operation even
with the stated restrictions.

>If you want abstract data types, you know where to find them....

Sure but all I want is a simple struct comparison :-)


--
Its a thin red line (and spelling error) between boring and borish.

Doug Gwyn

unread,
Jul 20, 1989, 7:45:46 PM7/20/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
>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.

Comparing padding is wrong anyway. Even if you could arrange for it to
"contain" some standard value (and I'm not sure how you could do that in
standards language), there is no constraint so far that says that value
must still be there later.

The obvious definition of struct comparison would be:
structs compare equal if and only if all their corresponding
members compare equal.
I assure you that it was considered as one of the zillion proposed C
language extensions received by X3, but its benefits were not shown to
outweigh its drawbacks.

Maarten Litmaath

unread,
Jul 20, 1989, 9:52:06 PM7/20/89
to
It seems I'm not the only one in favor of (a limited form of) struct
comparison. On my `traditional struct complex' example

struct complex {
int Re;
int Im;
} z, w;
...


if (z == w) ...

Henry Spencer wrote something like

"Then how about struct addition, sonny?"

to which I say

"Yes! Another useful struct operation!"

Of course the structure elements must be addable, i.e. no pointers etc..
(There we go again, Blair!)
Arrays would be added member-wise. Hmm, sounds interesting...
Another point raised by Henry

"How about polar representation of complex numbers and
non-uniqueness?"

was nicely dealt with by Roelof Vuurboom. Mathematical problems caused by
(inadequate) representation of mathematical quantities, and language
definitions are two different things. Here's another example:

prod = z * w;

would be equivalent to

prod.Re = z.Re * w.Re;
prod.Im = z.Im * w.Im;

which is NOT the representation of the product of the complex numbers
represented by `z' and `w'. So what? YOUR fault, not the language's.
To Henry's remark

"You want C++, not C."
I say
"For the `struct complex' example? Maybe. But does this mean
any innovation should be swept off the table?"

As Bernard A. Badger Jr. says, "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."

Roelof Vuurboom again:


"I've still got an awful lot of structs *which occur in the real world*
for which I can (and several times wished I could) do a sensible comparison."

--
"Mom! Eric Newton broke the day! In 24 |Maarten Litmaath @ VU Amsterdam:
parts!" (Mike Schmitt in misc.misc) |ma...@cs.vu.nl, mcvax!botter!maart

Guy Harris

unread,
Jul 21, 1989, 2:22:56 PM7/21/89
to
>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.

*I'd* rule it out, because it can give the wrong answer, but if you
don't care about getting the right answer, or know that in some
particular case it will never give the wrong answer, and you *really*
want a simplistic compare-all-bytes implementation, you can use "memcpy"
- which may be inlined in some implementations.

If you want a component-by-component comparison, you can write it
yourself, obviously, or wrap it in a macro if you use it a lot. Perhaps
not as convenient as having the compiler do it for you, but I'd find it
more convenient than, for every structure, deciding whether a compiler
notion of structure comparison would really do what I wanted (e.g., the
question of "do you compare pointer values or do you compare the values
to which they point), or would even work at all (e.g., a structure with
unions).

Guy Harris

unread,
Jul 21, 1989, 2:38:46 PM7/21/89
to
>1. unions, bit fields (and the related case of data padding)
>
>Agreed. But my argument above is that if I exclude these cases I've
>still got a very relevant operation.

I've seen no indication that it's sufficiently relevant *that it should
be added to the language*; any definition of structure comparison would
be peppered with caveats like "no unions" and "no arrays" and "it
compares pointer values, not what they point to" and the like.

Yes, there have been cases I've seen where it might have been
convenient, but I really *can* live with doing the member-by-member
comparison myself. And, given that there's no prior art, I agree with
X3J11's decision to leave it out. If somebody sticks it into their
compiler as an extension and we can really find out from experience
whether enough people actually *would* use it enough to justify its
existence, then it can be considered as an extension if it actually is
used enough and doesn't confuse people.

>3. polar complex example
>
>It took a while before I began to get the sneaky feeling that maybe
>Henry Spencer had put one over me here.
>
>His argument was that because a certain _mathematical_ concept (complex
>comparison) couldn't be supported this was (one of the) grounds for
>omitting a _language_ concept (struct comparison).

I think Henry's point, like mine, is that the total number of cases
where somebody, in effect, defines an equality operator over some data
type seems likely to be much larger than the number of cases where this
operator is just a member-by-member comparison; complex numbers
represented in polar form are one example. Given that, I'd like to see
some real-world experience with such a feature before seeing it blessed
in a standard....

The original poster *did*, in fact, effectively ask "why isn't structure
comparison in ANSI C"? The question was answered, by Henry and others,
and I have yet to see a *single* response to that answer that, to me,
would justify the inclusion of such a feature *in the ANSI C standard*,
given the lack of prior art (and yes, there *was* prior art for function
prototypes, namely in C++; it may not have been in an otherwise "pure" C
implementation, but at least it existed). I suspect *I* wouldn't use
structure comparison if it were available to me in C; I'm almost certain
I wouldn't use it if it were available to me in C++ - I'd define an "="
operator for the data type, instead, and not be forced to rely on
member-by-member comparison being the right answer.

Mike (I'll think of something yet) Meyer

unread,
Jul 21, 1989, 10:14:41 PM7/21/89
to

Can I point out something that I haven't seen mentioned here yet?

It's called "maintenance."

Consider the current situation. If you've got a structure that you
need to do comparison ons, and are thinking, you'll have an include
file with the structure & a comparison macro for that structure.

When you change the structure - in any way - you have the macro in the
same place, and can change it right there as apropos for the addition.

Now, assume you're using the hypothetical "struct comparison", you
don't have a macro - just the structure definition. If you change the
structure, you may not think about changing the equality test (no
macro nearby to remind you). When you do change it, you have to verify
that the default comparison is still legal and correct. If you need to
write a macro, you'll have to find every place that comparison is
used, and fix it. If the comparison is illegal, this isn't hard, just
tedious. If it's legal, it could be a pain.

While not something that would make you want to toss the facility
completely, it's yet another argument against it. The feature seems to
die the death of a thousand cuts.

BTW, my standard answer to people who _insist_ that C ought to have a
feature is:

Get a copy of GNU C, and add that feature. Then, when
they do the next revision of the standard, you'll have
"prior practice" for the committe. This is a lot more
likely to get it added than arguing about it on USEnet.
Besides which, you'll be able to write non-conforming
code that uses that feature in the meantime.


<mike

--
I went down to the hiring fair, Mike Meyer
For to sell my labor. m...@berkeley.edu
I noticed a maid in the very next row, ucbvax!mwm
I hoped she'd be my neighbor. m...@ucbjade.BITNET

Guy Harris

unread,
Jul 22, 1989, 4:38:29 PM7/22/89
to
>Henry Spencer wrote something like
>
> "Then how about struct addition, sonny?"
>
>to which I say
>
> "Yes! Another useful struct operation!"

Fine. Now what about complex *multiplication*? Doesn't sound like any
generally-useful structure multiplication operation would do the trick.
And what about division?

Sorry, but if you want complex numbers as a data type in C that uses C
operators, you can't get that just by pasting on new general "struct"
operators; you either have to add it to the language, or go the C++
route.

>Another point raised by Henry
>
> "How about polar representation of complex numbers and
> non-uniqueness?"
>
>was nicely dealt with by Roelof Vuurboom. Mathematical problems caused by
>(inadequate) representation of mathematical quantities, and language
>definitions are two different things. Here's another example:
>
> prod = z * w;
>
>would be equivalent to
>
> prod.Re = z.Re * w.Re;
> prod.Im = z.Im * w.Im;
>
>which is NOT the representation of the product of the complex numbers
>represented by `z' and `w'. So what? YOUR fault, not the language's.

Yes, but as far as I can tell the *ONLY* benefit of structure comparison
as a "native" C operation is that it applies a bit of syntactic sugar
frosting to the operation. Said frosting appears to have spoiled, in
both the cases of polar representation and in the case of complex
multiplication - so it appears that the "struct complex" example doesn't
cut it as an argument for adding new structure operators.

>To Henry's remark
>
> "You want C++, not C."
>I say
> "For the `struct complex' example? Maybe. But does this mean
> any innovation should be swept off the table?"
>
>As Bernard A. Badger Jr. says, "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."
>
>Roelof Vuurboom again:
>"I've still got an awful lot of structs *which occur in the real world*
>for which I can (and several times wished I could) do a sensible comparison."

OK, let's *see* the examples. I've only had any need for something
looking like structure comparison once or twice, and the inconvenience
of not having it was trivial. Somebody earlier said Ada had structure
comparsion; OK, how often is it *really* used? Not all features of a
given language are *ipso facto* useful.

And as for "does this mean any innovation should be swept off the
table", well, in a sense, yes. Innovation should be kept to a minimum
in language standards; some amount of successful "prior art" - or
unsuccessful "prior art" - should weigh a *lot* more in the decision to
put something into a standard than should theoretical arguments for or
against some feature. If you want structure comparison, put it into
*your* compiler (or GCC, or whatever), and report back on its success or
failure. Just because some feature seems nice does NOT mean it belongs
in the current C standard.

Doug Gwyn

unread,
Jul 23, 1989, 7:20:39 AM7/23/89
to
In article <22...@auspex.auspex.com>, g...@auspex.auspex.com (Guy Harris) writes:
> Sorry, but if you want complex numbers as a data type in C that uses C
> operators, you can't get that just by pasting on new general "struct"
> operators; you either have to add it to the language, or go the C++
> route.

That's also my general observation: When I need composite objects, I
practically always find that I also need operations on them beyond any
simple model that could reasonably be supported directly via language
operators. Complex multiplication is just one of the simplest examples.
Since I have to provide a set of explicitly programmed operations anyway,
it is not a lot of additional bother that the language doesn't directly
support a few of them.

Donn Terry

unread,
Jul 23, 1989, 9:20:58 PM7/23/89
to
Personal opinion:

Omitting comparison of at least a limited range of structs presents
a class of problems that has not been addressed here so far.

There are certain predefined types in classical UN*X (and probably other
OSs as well) that would "like" to be structs (or at least objects larger
than long). dev_t is a good example. For historical reasons, usually
associated with comparisons on such types, they must be constrained to
integral (or at least arithmetic) types.

Because ANSI C prohibits comparisons on such larger types, standardizers
of other things (e.g. POSIX) are constrained:

1) require integral/arithmetic types, and force unnatural kluges
on some OS's (more than 32-bits worth of I/O addressability,
allowing for type modifiers: try to cram it into an dev_t or
force an otherwise unneeded long long long long... type).
2) Define new types for the standard, and define operations on
those types for all relevant operations. (Typically at least
3: comparison, and some modifier and it's converse.)
3) Break existing applications by permitting/requiring struct types
that will break the applications that use the object.

If ANSI C had permitted even a strongly constrained comparable struct type
these problems would have been eliminated. (E.g. add "comparable" struct
to the language: compilers would be permitted to reorder to allow comparison
as a byte-by-byte comparison; possibly prohibit pointers, possibly prohibit
or constrain unions.) Even off_t would have been helped, as only the add
and subtract operators would have to be macros were this possible. Those
are not _too_ common.

(Something has to give with off_t, and soon; 4Gb disks are coming along
very soon. It would be nice to find a way to deal with them without
having to rewrite every use of off_t and lseek() in the world. The
ANSI C solution might work (I forget the names, but there is a solution
for stdio), but it does require a lot of rewrite of existing applications.)

Donn Terry
HP Ft. Collins
Chair 1003.1 (and speaking only for himself)

Peter da Silva

unread,
Jul 23, 1989, 9:40:28 PM7/23/89
to
In article <22...@auspex.auspex.com>, g...@auspex.auspex.com (Guy Harris) writes:
> notion of structure comparison would really do what I wanted (e.g., the
> question of "do you compare pointer values or do you compare the values
> to which they point),

You compare pointer values.

> or would even work at all (e.g., a structure with
> unions).

This should be illegal (as should initialising a union).


--
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Business: pe...@ficc.uu.net, +1 713 274 5180. | "...helping make the world
Personal: pe...@sugar.hackercorp.com. `-_-' | a quote-free zone..."
Quote: Have you hugged your wolf today? 'U` | -- h...@cernvax.cern.ch

Peter da Silva

unread,
Jul 24, 1989, 9:47:41 AM7/24/89
to
In article <10...@smoke.BRL.MIL>, gw...@smoke.BRL.MIL (Doug Gwyn) writes:
> That's also my general observation: When I need composite objects, I
> practically always find that I also need operations on them beyond any
> simple model that could reasonably be supported directly via language
> operators. Complex multiplication is just one of the simplest examples.

This is a reasonable point, but do keep in mind that this is also true of
simple objects. For example, when dealing with !(char *)! objects, don't
you practically always find that you need operations on them beyond any


simple model that could reasonably be supported directly via language

operators? !strcmp()! is just one of the simplest examples.

R. Vuurboom

unread,
Jul 24, 1989, 2:05:50 PM7/24/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
|
|I've seen no indication that it's sufficiently relevant *that it should
|be added to the language*; any definition of structure comparison would
|be peppered with caveats like "no unions" and "no arrays" and "it
|compares pointer values, not what they point to" and the like.
|

Ok, let me try and put my money where my mouth is:

Structure comparison is defined for structures which are recursively
derived from basic, enumerated, pointer or structure types.

Two structs of the same derived type for which structure comparison
is defined compare equal if and only if each member (recursively)
compares equal.


Which points out that in order to define something you don't
necessarily need to state what it isn't but just what it is.


|Yes, there have been cases I've seen where it might have been
|convenient, but I really *can* live with doing the member-by-member
|comparison myself.

Agreed, so can I. I can live without struct assignment too but I kind of
like having it.

I don't think the "living without" argument is really fair. We can all
live without a lot of things (probably even C :-).

|And, given that there's no prior art, I agree with
|X3J11's decision to leave it out.


Which makes me start wondering about volatile or - to go to another extreme -
const.

|If somebody sticks it into their
|compiler as an extension and we can really find out from experience
|whether enough people actually *would* use it enough to justify its
|existence, then it can be considered as an extension if it actually is
|used enough and doesn't confuse people.
|

The above I consider valid arguments, translating:

Is it relevant? viz. can you expect it to be used in "mainstream" programming?
Is it straightforward? Perhaps to put it another way: is it "natural".


|The original poster *did*, in fact, effectively ask "why isn't structure
|comparison in ANSI C"? The question was answered, by Henry and others,
|and I have yet to see a *single* response to that answer that, to me,
|would justify the inclusion of such a feature *in the ANSI C standard*,
|given the lack of prior art (and yes, there *was* prior art for function
|prototypes, namely in C++; it may not have been in an otherwise "pure" C
|implementation, but at least it existed).

Obviously I can't be sure that any particular argument will convince you
but this one might convince me:

enum make_t {BMW,PEUGEOUT,RENAULT,MERCEDES,...
enum colour_t {CHROMIUM_RED,CANARY_YELLOW,

typedef car
{
make_t make;
colour_t colour;
}

...
for( i=0; i < nr_cars_in_stock; i++ )
{
..
if ( car_wanted == cars_in_stock[i] )

...


|I suspect *I* wouldn't use
|structure comparison if it were available to me in C; I'm almost certain
|I wouldn't use it if it were available to me in C++ - I'd define an "="
|operator for the data type, instead, and not be forced to rely on
|member-by-member comparison being the right answer.

The choice of whether you would want (need) to use abstract data typing
or data structure comparison is really quite clear cut. It is the cut
between whether the data structure represents an abstraction (complex
numbers case in point) or represents a combinatoric. In the first
case the object is _more_ than the sum of its parts. In the second case
the object _is_ the sum of its parts. A complex number has "more" meaning
than a pair of reals hence the extra operations needed to bring out this
meaning. A red car does not represent a higher abstraction level than the
concepts red and car considered separately. To put it simply, all applications
that use combinatoric objects (in the sense I've defined) could (and I
think would) use struct comparison.

In this particular application area struct comparison is both relevant and
straightforward.

Attempting to quantify how often this comes up and how often it needs to
come up to make into X3J11 is something I find impossible to do. All I
can say is that I have come across the above application area a number of
times.

--
I don't know what the question means, but the answer is yes...
(overheard on comp.lang.misc)

Guy Harris

unread,
Jul 24, 1989, 4:02:27 PM7/24/89
to
>> notion of structure comparison would really do what I wanted (e.g., the
>> question of "do you compare pointer values or do you compare the values
>> to which they point),
>
>You compare pointer values.

Which may not always correspond to what you want; i.e., "these two
structure values have the same values in all their fields" may not be
equivalent to "the objects these structures represent are equal". If,
say, experience with Ada indicates that they are frequently equivalent,
and that people do use structure comparison heavily, that experience
might, with some care, be applicable to C; otherwise, the right thing to
do is NOT to put it into the standard, but put it into GCC or some other
compiler and see how often it's really used.

Badger BA 64810

unread,
Jul 24, 1989, 6:16:27 PM7/24/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
[..stuff deleted...]

>I've seen no indication that it's sufficiently relevant *that it should
>be added to the language*; any definition of structure comparison would
>be peppered with caveats like "no unions" and "no arrays" and "it
>compares pointer values, not what they point to" and the like.

When I entered this discussion, it was centering on whether struct comparison
was a well-defined and useful operation. I think that has been established
for structs not containing unions. Whether to add it to the language --
in particular whether to include it in ANSI C -- is another, more
(mostly?) political question.

>
>Yes, there have been cases I've seen where it might have been
>convenient, but I really *can* live with doing the member-by-member

>comparison myself. And, given that there's no prior art, I agree with
>X3J11's decision to leave it out. If somebody sticks it into their


>compiler as an extension and we can really find out from experience
>whether enough people actually *would* use it enough to justify its
>existence, then it can be considered as an extension if it actually is
>used enough and doesn't confuse people.

There may be ``no prior art'' with standard C, but let's not ignore
prior art from other programming languages. Struct comparison is less
confusing than unions and bit fields. Anyway, Real Programmers (TM)
like Guy probably aren't using struct assignment and function return
values either (:-).


>>3. polar complex example
>>
>>It took a while before I began to get the sneaky feeling that maybe
>>Henry Spencer had put one over me here.
>>
>>His argument was that because a certain _mathematical_ concept (complex
>>comparison) couldn't be supported this was (one of the) grounds for
>>omitting a _language_ concept (struct comparison).
>
>I think Henry's point, like mine, is that the total number of cases
>where somebody, in effect, defines an equality operator over some data
>type seems likely to be much larger than the number of cases where this
>operator is just a member-by-member comparison; complex numbers
>represented in polar form are one example. Given that, I'd like to see
>some real-world experience with such a feature before seeing it blessed
>in a standard....
>

>The original poster *did*, in fact, effectively ask "why isn't structure
>comparison in ANSI C"? The question was answered, by Henry and others,
>and I have yet to see a *single* response to that answer that, to me,
>would justify the inclusion of such a feature *in the ANSI C standard*,
>given the lack of prior art (and yes, there *was* prior art for function
>prototypes, namely in C++; it may not have been in an otherwise "pure" C

>implementation, but at least it existed). I suspect *I* wouldn't use


>structure comparison if it were available to me in C; I'm almost certain
>I wouldn't use it if it were available to me in C++ - I'd define an "="
>operator for the data type, instead, and not be forced to rely on
>member-by-member comparison being the right answer.

Of course, you wouldn't be *forced* to rely on member-by-member comparison!
You could still write your own function, or more likely macro. Careful
programmers would probably do that anyway, to maintain the abstraction.
However, wouldn't it be nice if you *could* write

#define COMPLEX_EQUAL(a,b) ((a) == (b))

instead of

#define COMPLEX_EQUAL(a,b) ((a).real == (b).real && (a).imag == (b).imag)

(Whew! That was a really tough one!)


What if we define:

typedef struct _vector_t {int x,y,z;} vector_t;
typedef struct _matrix_t {vector_t x,y,z;} matrix_t;

static const matrix_t identity_matrix = {{1,0,0},{0,1,0},{0,0,1}};
static matrix_t m1 = {{1,0,0},{0,0,1},{0,1,0}};

It may be convenient to inquire:
{ int flag = m1 == identity_matrix; ....}

Isn't it good?


I'll quote from ``C: A Reference Manual'' by Harbison and Steele,

p 106:
5.7.1 Operations on Structures
...
It is not permitted to compare two structures for equality. An
object of a structure type is a sequence of components of other
types. Because certain data objects may be constraind by the
target computer to lie on certain addressing boundaries, a
structure object may contain ``holes,'' storage units that do not
belong to any component of the structure. The holes would make
equality tests implemented as a wholesale bit-by-bit comparison
unreliable, and component-by-component equality tests would be too
expensive. (Of course, the programmer may write
component-by-component equality functions.)

I don't find this persuasive. If an equality test is required, the
programmer is going program it anyway. The problems performing the test
don't go away just because the compiler has passed the responsibility to
the programmer. Perhaps the compiler will be able to produce better code
than the average programmer. If not, (and I'm repeating myself here,)
a programmer can usually avoid any language feature he doesn't like and
do it the old-fashioned way.

I don't know much about the politics and practicalities of introducing
concepts to the current ANSI C. I've heard that the purpose is more to
standardize existing practice than to correct deficiencies that aren't
outright faults. So be it.

I'm posting more in the hope of rescuing this simple idea from the
criticisms by Guy and others that struct comparison is complex,
ill-defined or not useful.

Dave Decot

unread,
Jul 24, 1989, 7:25:56 PM7/24/89
to
I really don't see any problem with a definition of structure comparison
that said two comparable structures match if and only if the corresponding
elements compare equal.

If an implementation wants to make holes in structures, that's fine;
it just has to deal with avoiding the holes when generating code to
compare the structures. An application wishing to compare strucutres
(or things which are potentially structures) should be willing to
put up with a little delay.

Or, if it's smart enough to notice that the particular structures
involved are never modified via aliases, the compiler could initialize
them with 0's in the holes and not worry about them when comparing.

As Donn Terry points out, most of the structures one wants to compare
in practice have no holes, anyway.

Dave

Jeffrey Kegler

unread,
Jul 24, 1989, 10:29:49 PM7/24/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
>>You compare pointer values.
>
>Which may not always correspond to what you want; i.e., "these two
>structure values have the same values in all their fields" may not be
>equivalent to "the objects these structures represent are equal". If,
>say, experience with Ada indicates that they are frequently equivalent,
>and that people do use structure comparison heavily, that experience
>might, with some care, be applicable to C; otherwise, the right thing to
>do is NOT to put it into the standard, but put it into GCC or some other
>compiler and see how often it's really used.

Precisely right. If we were arbitrarily stuck with an untested
interpretation of structure comparison, we might soon regret it. I
have my guess as the best way to compare structures by default (ignore
unions and padding, compare pointers by value), but any guess that
winds up in the standard we would be stuck with for a long time to
come.

The proper way to lobby for your favorite method of structure
comparison is to hack GCC, and submit it to a jury of our peers. Just
sticking a best guess into a standard is not a good idea. The ANSI C
Committee deserves congratulations for having recognized this.
--

Jeffrey Kegler, President, Algorists,
jef...@algor2.UU.NET or uunet!algor2!jeffrey
1762 Wainwright DR, Reston VA 22090

Doug Gwyn

unread,
Jul 25, 1989, 11:04:18 AM7/25/89
to
In article <1204...@hpfcdc.HP.COM> do...@hpfcdc.HP.COM (Donn Terry) writes:
>(Something has to give with off_t, and soon; 4Gb disks are coming along
>very soon. It would be nice to find a way to deal with them without
>having to rewrite every use of off_t and lseek() in the world. The
>ANSI C solution might work (I forget the names, but there is a solution
>for stdio), but it does require a lot of rewrite of existing applications.)

The natural and efficient representation for fpos_t (the generalization
of off_t) in virtually any large-system environment would be such that
special arithmetic is required to maintain properly normalized (block,
byte) information. If unnormalized arithmetic is allowed, then you need
a special normalizing comparison operation. It's considerations like
these that convinced many of us that the gain in supporting more extensive
structure operations directly in the language would not be worth the trouble.

David Keppel

unread,
Jul 25, 1989, 12:26:11 PM7/25/89
to
>[Ongoing discussion of struct comparison]

I think that the discussion of structure operators has moved out of
the charter of the comp.std.c newsgroup (until the next ANSI
committee meeting :-).

Please follow up to comp.lang.c and/or comp.lang.misc.

;-D on ( Structure isolationism ) Pardo
--
pa...@cs.washington.edu
{rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo

Raymond Dunn

unread,
Jul 25, 1989, 3:55:58 PM7/25/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
>.........If,

>say, experience with Ada indicates that they are frequently equivalent,
>and that people do use structure comparison heavily, that experience
>might, with some care, be applicable to C

I'm glad Ada has been mentioned, because that language demonstrates clearly the
problems when all things for all men are added to a language.

'C' adequately provides the basic tools you need to build your own pet version
of struct comparison, as well as most of the other things on your particular
wish-list.

'C' is already starting to suffer from committee-itis and library-itis.

Keep it lean... keep it lean!!!
--
Ray Dunn. | UUCP: ..!uunet!philmtl!ray
Philips Electronics Ltd. | TEL : (514) 744-8200 Ext: 2347
600 Dr Frederik Philips Blvd | FAX : (514) 744-6455
St Laurent. Quebec. H4M 2S9 | TLX : 05-824090

Guy Harris

unread,
Jul 25, 1989, 8:07:01 PM7/25/89
to
>If ANSI C had permitted even a strongly constrained comparable struct type
>these problems would have been eliminated. (E.g. add "comparable" struct
>to the language:

OK, what if I want to see if one file offset is larger than, or smaller
than, another? It may be uncommon, or it may not - until somebody's
scoured a large body of code, I'd assume there is code that does
comparisons on file offsets, since it is permissible on integral
types....

>compilers would be permitted to reorder to allow comparison as a
>byte-by-byte comparison;

Reorder structure members? I think that's a separate issue....

>Even off_t would have been helped, as only the add and subtract operators
>would have to be macros were this possible. Those are not _too_
>common.

Perhaps add and subtract aren't as common as other operators, but I'd
still be a bit annoyed if I couldn't add and subtract file offsets;
unlike structure comparison, I've used addition of file offsets on a
number of occasions.

>(Something has to give with off_t, and soon; 4Gb disks are coming along
>very soon. It would be nice to find a way to deal with them without
>having to rewrite every use of off_t and lseek() in the world.

Me, I'd vote for "long long int", which I doubt would be "otherwise
unneeded" - Convex, at least, thought they needed it. As an integral
type, it should require less rewriting (although there is the problem
that existing systems define "off_t" otherwise - but that problem exists
with other proposed changes to "off_t" as well).

Guy Harris

unread,
Jul 25, 1989, 8:10:37 PM7/25/89
to
>Just like the compiler doesn't have enough information to
>initialize a union, right? !
>
>A simple rule like comparing first members of unions and the
>pointers themselves would work nicely in a lot of cases and
>match the way initialization works.

Uh, as far as I'm concerned, the "first member" rule's only use is to
give a meaning to the default initialization of unions. It means I
can't initialize, say, an array of union types or objects containing
union types if different elements of that array have different union
members "active", for example (e.g., a symbol table, with symbols
having, say, string, integral, or floating-point values, selected by a
discriminator - if I want the initial symbol table to have values of
more than one type, I lose).

Had it not been for the necessity of giving *some* meaning to
initialization of unions, I'd just as soon have left initialization of
them undefined....

Norman Diamond

unread,
Jul 25, 1989, 10:08:52 PM7/25/89
to
In article <1204...@hpfcdc.HP.COM> do...@hpfcdc.HP.COM (Donn Terry) writes:

>(Something has to give with off_t, and soon; 4Gb disks are coming along
>very soon. It would be nice to find a way to deal with them without
>having to rewrite every use of off_t and lseek() in the world.

It is time to learn a lesson from the 80*86 family. Near and far are
kluges. It is a pain in the *** to be unable to do pointer arithmetic
in a reasonable fashion.

The lesson? Integral types and off_t will be kluges. It will be a pain
in the *** to be unable to do off_t arithmetic in a reasonable fashion.

Any vendor who supplies 4Gb disks should supply a long long type in
their C compilers. Quality of implementation issues should encourage
this semi-portable extension. This will save many pains in the ***.
If the marketplace allows this to occur, then C-0X will standardize it.

nevin.j.liber

unread,
Jul 27, 1989, 10:57:21 PM7/27/89
to
In article <24...@trantor.harris-atd.com> bba...@x102c.harris-atd.com (Badger BA 64810) writes:

>When I entered this discussion, it was centering on whether struct comparison
>was a well-defined and useful operation. I think that has been established
>for structs not containing unions. Whether to add it to the language --
>in particular whether to include it in ANSI C -- is another, more
>(mostly?) political question.

It is NOT mostly a political question! There are problems that would
be introduced with it! Consider the following scenario:

Jane Programmer, fresh out of college, reads all about C with the
struct equality extension (C-SEE :-)), and is raring to go program
with it. She, along with her colleages, write 10,000,000 lines of code
in C-SEE. An example of a struct used in this code (and there are
thousands) is:

struct typical
{
int foo;
/* ... hundreds of variables */
char bar;
}

Three years later, you come on the scene. Your boss asks you to make
some enhancements to the ten million line program, and one of them requires
you to change struct typical (among other things). Now it looks like:

struct typical
{
int foo;
/* ... hundreds of variables */
char bar;
short uh_oh;
}

Guess what happens? The code breaks!! By seemingly innocently adding
a field to the struct, you now have to go through and fix all the code
you broke. If you are lucky, and you remembered to do this before you
sent the code to the testers, you could get the compiler to find all
the instances of the struct (by simply adding a union to the struct
typical definition, and having the compiler give you the error lines),
but that isn't the point.

Also, how do you plan on fixing the code? Are you going to think about
each and every struct comparison, and decide on-the-spot whether or not
the rewrite it the way you would in standard C (if a union was added to
typical, you would *have* to rewrite ALL the C-SEE dependent stuff)?


The only situation where the C-SEE extension would be useful is when
you know that you just want to compare all the elements of the struct
together. In order to do this, you can't abstract over the struct; you
have to *know* what each element is in order to use C-SEE safely. It
is better self-documentation, as well as safer, to just write out the
member comparisions longhand.
--
NEVIN ":-)" LIBER AT&T Bell Laboratories nev...@ihlpb.ATT.COM (312) 979-4751

Guy Harris

unread,
Jul 28, 1989, 1:38:48 PM7/28/89
to
...

> char bar;
> short uh_oh;
> }
>
>Guess what happens? The code breaks!! By seemingly innocently adding
>a field to the struct, you now have to go through and fix all the code
>you broke.

Are you implying here that:

1) "uh_oh" isn't supposed to be compared when you do structure
comparisons

or

2) C-SEE compiles all structure comparisons into comparisons of
all the bytes of the structure?

If 2), I think it's been established that the *only* correct definition
of structure comparison would be member-by-member, and if that means the
structure comparison doesn't compile into e.g. a single "CMPCn"
instruction on a VAX, too bad. While this may surprise some users of
the structure comparison construct (and, if it surprises a lot of them,
it means advocates of structure comparison had better be prepared to
educate said users), it means that adding a structure member that causes
padding to be added to a structure won't break structure comparisons.

Peter da Silva

unread,
Jul 28, 1989, 3:25:52 PM7/28/89
to
In article <20...@cbnewsc.ATT.COM>, nev...@cbnewsc.ATT.COM (nevin.j.liber) writes:
> Guess what happens? The code breaks!!

Why?

> It is better self-documentation, as well as safer, to just write out the
> member comparisions longhand.

And how many times do you forget one?

Tim McDaniel

unread,
Jul 29, 1989, 1:39:45 AM7/29/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris)
writes:
>OK, what if I want to see if one file offset is larger than, or smaller
>than, another?
...

>Perhaps add and subtract aren't as common as other operators, but I'd
>still be a bit annoyed if I couldn't add and subtract file offsets;
>unlike structure comparison, I've used addition of file offsets on a
>number of occasions.

The BSD 4.3 man page for fseek(3S) and ftell(3S) says:

_Ftell_ returns the current value of the offset relative to
the beginning of the file associated with the named _stream_.
It is measured in bytes on UNIX; on some other systems it is
a magic cookie, and the only foolproof way to obtain an
_offset_ for _fseek_.

K&R 2, 1st edition, p. 248, says (for fseek):

For a binary file, the position is set to _offset_ characters
from _origin_, which may be SEEK_SET (beginning), SEEK_CUR
(current postion), or SEEK_END (end of file). For a text stream,
_offset_ must be zero, or a value returned by _ftell_ (in which
case _origin_ must be SEEK_SET).

Thus, in pANS C, a *text* stream offset may indeed be a "magic
cookie", for which comparison and arithmetic is undefined. Binary
mode requires an actual character number. (Personally, I see no point
in having the distinction; I'd like to see all _offset_s be magic
cookies. It's too late, now that X3J11 has acted.)

--
"Let me control a planet's oxygen supply, and I don't care who makes
the laws." - GREAT CTHUHLU'S STARRY WISDOM BAND (via Roger Leroux)
__
\ Tim, the Bizarre and Oddly-Dressed Enchanter
\ mcda...@uicsrd.csrd.uiuc.edu
/\ mcdaniel%uicsrd@{uxc.cso.uiuc.edu,uiuc.csnet}
_/ \_ {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel

Guy Harris

unread,
Jul 29, 1989, 5:07:09 PM7/29/89
to
>The BSD 4.3 man page for fseek(3S) and ftell(3S) says:

Which is irrelevant, since the original poster was talking about, among
other things, "off_t" from POSIX, which *is* an integral type, and POSIX
file offsets, which *are* measured in bytes. The fact that, in ANSI C,
you can get away with "fseek()" offsets not being integral types isn't
relevant; in POSIX, they'd better be integral types, and absent
something like "long long int", which isn't in strict ANSI C, the best
you can do is "long", which in many implementations is, for better or
worse, 32 bits.

Marc W. Mengel

unread,
Aug 3, 1989, 11:21:17 AM8/3/89
to
In article <22...@auspex.auspex.com> g...@auspex.auspex.com (Guy Harris) writes:
>>Just like the compiler doesn't have enough information to
>>initialize a union, right? !
>Uh, as far as I'm concerned, the "first member" rule's only use is to
>give a meaning to the default initialization of unions. It means I
>can't initialize, say, an array of union types or objects containing
>union types if different elements of that array have different union
>members "active"...

Why can't we adopt a simple rule like initializing the first union member
of the right type? something like

union { char c; int i; float f;} bozo[3]={ (int)5, (char)5,(float)5};

would make it clear which union member is being initialized; if there
are two union members of the same type it doesnt matter which one
of the two you initialize. For more complicated types (unions of
structures, etc.) you would have to recursively check the types of
members to find a match, but you already have to do the recursive
checks to match curly braces to sub-structures or arrays are in
the right place, so...

>Had it not been for the necessity of giving *some* meaning to
>initialization of unions, I'd just as soon have left initialization of
>them undefined....

--
Marc Mengel mme...@cuuxb.att.com
attmail!mmengel
...!{lll-crg|att}!cuuxb!mmengel

0 new messages