Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!bloom-beacon!newman From: newman@athena.mit.edu (Ron Newman) Newsgroups: comp.lang.c Subject: Incomplete structure declarations as opaque data types Message-ID: <1396@bloom-beacon.MIT.EDU> Date: Sat, 5-Sep-87 02:59:23 EDT Article-I.D.: bloom-be.1396 Posted: Sat Sep 5 02:59:23 1987 Date-Received: Sun, 6-Sep-87 01:57:48 EDT Sender: daemon@bloom-beacon.MIT.EDU Reply-To: newman@athena.mit.edu (Ron Newman) Organization: Massachusetts Institute of Technology Lines: 56 The following program is legal, lint-free C, and demonstrates how one can implement an abstract ("opaque") data type: typedef struct _ThingRec ThingRec, *Thing; extern Thing CreateThing(); main() { Thing thing = CreateThing (4, 7); OperateOnThing(thing); DestroyThing (thing); } The idea here is that only the module(s) that implement Thing need to have a complete declaration of struct _ThingRec. Anyone who just uses a Thing can use the incomplete declaration above, and the details of a Thing are hidden from him. Of course, in real life, the first two lines would appear in a header file "Thing.h" shared by all users of Thing. The complete declaration would appear in "ThingPrivate.h", shared by all files that implement the Thing data type. This is a standard technique in "advanced" languages like Mesa and Modula-2; I was surprised at first to find that C (perhaps inadvertently) allows it as well. I have found it to be a very useful technique for hiding the "guts" of a data structure from clients who have no need to look inside the structure. However, this program raises some interesting questions about pointer representation. For this to work, all structure pointers must be the same size, regardless of the structure contents. Otherwise, the compiler would not know how much storage to allocate for a Thing. In addition, it appears that all structure pointers must have the same REPRESENTATION too. Otherwise, the caller and callee of CreateThing, OperateOnThing, and DestroyThing would fail to agree on the representation. In addition, it's legal to write char *p = (char *) thing; so the compiler must know how to cast a (struct foo *) to (char *) without knowledge of what (struct foo) really is. My question: since this program is legal, doesn't C implicitly require all structure pointers to have identical size and representation? /Ron Newman MIT Project Athena note 1: amazingly, even this is legal: extern ThingRec thingRec; Thing thing = &thingRec; note 2: the program is accepted, without warnings, even by the IBM RT "High C" compiler, which claims to be ANSI-conforming.