garry@batcomputer.tn.cornell.edu (Garry Wiegand) (11/19/86)
The new C incipient-spec has a primitive datatype called "void *". It has the property that a pointer of any type cast to (void *) and back again is guaranteed to emerge unharmed. I use this heavily to pass pointers (to structures) through utility routines which do not know what type of pointer is coming down, and back again to action routines which *do* know what type is coming. What I would like is to be able to do the same thing with *any* kind of (primitive) value, not merely pointer values!!! (Why do things half-way in the language ??) On many/most machines, "unknown" (somebody was brain-damaged when they overloaded the word "void"!) would be equivalent to: (unknown)char -> (double)char (unknown)pointer -> (double)(long)pointer (unknown)short -> (double)short (unknown)long -> (double)long (unknown)int -> (double)int (unknown)float -> (double)float I can get away with this because doubles almost always have more precision in them than any of the other datatypes. I can't #define "unknown" as "double" because (unknown)pointer will break on many (broken) compilers. It can't be (double)(long) because (unknown)float will break. So I need it as a primitive. Ideally it would just be a 64-bit bitmask internally rather than a double, to avoid unnecessary conversions. A fringe benefit is that I can declare *actual variables* to be of type "unknown", and so avoid having to play with unions of {int, char, float, double, void *}. Tests for equality should still work. Tests for ordering (<, >) would work easily on a doubles-implementation but might be tough on bitmasks. Yah, I know I'm too late. Can I at least have (double)pointer not break, pleeez? Does the spec already say that (double)pointer is as legit as and equivalent to (double)(long)(void *)pointer ?? garry wiegand (garry%cadif-oak@cu-arpa.cs.cornell.edu)
karl@haddock.UUCP (Karl Heuer) (12/05/86)
In article <1542@batcomputer.tn.cornell.edu> garry%cadif-oak@cu-arpa.cs.cornell.edu.arpa writes: >I use [void *] heavily to pass pointers (to structures) through utility >routines which do not know what type of pointer is coming down, and back >again to action routines which *do* know what type is coming. > >What I would like is to be able to do the same thing with *any* kind of >(primitive) value, not merely pointer values!!! There are a few routines, e.g. memcpy(), which can behave reasonably on any pointer type (cast into "void *"). I find it hard to imagine a routine that would operate portably on both "double" and "char *" without knowing which. >... So I need it as a primitive. Ideally it would just be a 64-bit bitmask >internally rather than a double, to avoid unnecessary conversions. From this I assume that you want "(double)unk" and "(int)unk" to just read the bits directly and not convert -- in other words, the operation performed by a union rather than a cast. >A fringe benefit is that I can declare *actual variables* to be of >type "unknown", and so avoid having to play with unions of {int, char, >float, double, void *}. You can declare actual variables of type union { int, ... }. Let me make a counterproposal (one which is more likely to be accepted by the C community): typedef union { int asint; char *asstring; double asreal; } universe; universe u; int i; ... u = (universe)i; This cast (currently illegal) would be equivalent to "u.asint = i", but is more powerful since it can be used in contexts other than assignment. For example, I could now initialize an array of unions at compile time: universe a[] = { (universe)12, (universe)"hello", (universe)5.6 }; The reverse cast "(int)u" could be allowed for completeness, but wouldn't be as useful since "u.asint" provides the same functionality. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
throopw@dg_rtp.UUCP (Wayne Throop) (12/08/86)
> karl@haddock.UUCP (Karl Heuer) > Let me make a [proposal] > the C community): > typedef union { int asint; char *asstring; double asreal; } universe; > universe u; int i; > ... > u = (universe)i; Oooooooh! I LIKE it. But I'd druther have the general ability to coin struct and union constants... passing small structs full of bitfields to functions that are manufactured out of integers on the fly is a more common problem. -- A LISP programmer knows the value of everything, but the cost of nothing. --- Alan J. Perlis -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
jsdy@hadron.UUCP (Joseph S. D. Yao) (12/15/86)
In article <1542@batcomputer.tn.cornell.edu> garry%cadif-oak@cu-arpa.cs.cornell.edu.arpa writes: >the property that a pointer of any type cast to (void *) and back again >is guaranteed to emerge unharmed. >What I would like is to be able to do the same thing with *any* kind of >(primitive) value, not merely pointer values!!! (Why do things half-way >in the language ??) > (unknown)pointer -> (double)(long)pointer > (unknown)long -> (double)long Unfortunately, there's no guarantee that a double will not lose low-order bits in the mantissa when converting a long. This is especially a problem if the "long" happens to be a pointer. E.g., 32-bit long 0x7fffffff to 32-bit double with 8-bit exponent and 24-bit mantissa loses 8 bits of precision. (Just f'r'instance.) Unions are sometimes used for this purpose: they are guaranteed to be as large as the largest object contained therein. -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP} jsdy@hadron.COM (not yet domainised)