views:

409

answers:

5

I'm learning C and I'm reading about type equivalence.

I'm curious, does anyone have an opinion why they used structural equivalence for arrays and pointers but they used declaration equivalence for structs and unions?

Why the disparity there? What is the benefit of doing declaration equivalence with structs/unions and structural equivalence for everything else?

+5  A: 

I'm sure others will present C specific information, but I'll mention that type-equivalence is one of the classic main problems in programming languages theory. Determining whether two types are actually equivalent is a much trickier problem than it may seem.

For example, here are some overview slides from an academic course just to give you a taste of the headache.

Uri
+3  A: 

I'm sure it was because it looked like a good idea at the time.

Don't try to overthink the design of C. Kernighan & Ritchie were designing a system implementation language that might be good for other things, and wound up with decisions they regretted later (operator precedence being the best documented). Some of the issues were cleaned up by the Standards Committee, and others were too deeply ingrained.

As Uri points out in his answer, type equivalence is a difficult problem, and is therefore one of those likely to have been punted by K&R in a desire to get a working compiler soon rather than a clean language design later.

David Thornley
+3  A: 

In a lot of ways c is a clean expression of assembly idiom from the 1970s. Arrays on these processors are implemented directly using pointers, and c simply copies that fact.

dmckee
Not all processors. VAX very nearly had arrays as a first-class data type, using the INDEX instruction, and I seem to remember that some of the Prime hardware had actual array types. Not so sure about the latter.
John Saunders
+3  A: 

Structural equivalence is difficult to check. Pointers and arrays are pretty simple, but structs and union types are more complex. Testing for structural equivalence is very difficult on these complex types, but easier for pointers and arrays.

EDIT

Originally I had written an answer that dealt with value equivalence instead of type equivalnce, so it wasn't really n answer to this question. I did receive a few upvotes on it, though, so I decided to keep in here.

What I know about [value equivalence], is that pointers and arrays always have a pretty simple layout in memory. This which makes it easy to do a simple byte-for-byte comparison.

For structs and union, this memory layout isn't necessarily this simple. You could for example, have a struct with an int (32 bit) and a double (64 bit). Such a struct requires 128 bits of memory, 32 of which aren't actually relevant for comparison. So, byte-forbyte comparison is out of the question. So, declaration equivalence is just easier to implement.

Rik
"type equivalence" != "value comparison", I'm pretty sure...
RBerteig
You are absolutely right! I completely mixed up the issues. Editing...
Rik
+1 for the edit and succinct answer. ;-)
RBerteig
+3  A: 

Don't underrate Dennis Ritchie. Every statically typed language should have a way to create an abstract type which it is impossible for a user to forge. For this you need a type construct or declaration construct that is generative, i.e., every instance of the construct generates a fresh type, distinct from any other. Such a construct is vital if you want to keep other people's mitts off your data. (For plenty of examples, see Dave Hanson's book C Interfaces and Implementations.)

So here values p1 and p2 have different types but the same representation:

struct { float x, y } p1;
struct { float x, y } p2;

Why pick struct to be generative? Because it's general enough to allow a wide range of convenient representations. union is a bit of a stretch, but I suspect it's "collateral design"; in C's type system, union behaves as much list struct as possible, which simplifies the compiler.

Incidentally, "declaration equivalence" is a term I have never heard before. 25 years ago terms like "name equivalence", "structural equivalence", and "occurence equivalence" were popular. Today type systems are much more formal, and equivalence is typically defined by logical rules rather than informal English. When it is helpful to resort to informal English, I usually find that the idea of "generativity" has more explanatory power than inventing a new name for the equivalence rules of each new language.

Norman Ramsey