karl@haddock.ima.isc.com (Karl Heuer) (09/01/89)
In article <10897@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <1545@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >>... so that (use int)x means treat x as type int no matter what it was. >>This is another example of keeping the tools from the programmer. > >No, this is another example of not knowing how to use the tools that are >already provided. I agree with Herman, for a change. An lvalue take-as operator is one of the few "universal escapes" that is not provided by C, and is not easy to fake for the general case. (I believe it's Modula-2 that has this feature as a builtin operator named ESCAPE.) >If it wasn't represented with the same number of bits as an int, what >could this possibly mean? If you're going to invent something, make sure >that it is sufficiently useful first. Those are two separate issues. One could probably formalize the semantics via an equivalent statement about unions. If x has more bits than an int, it's well-defined (though perhaps not very useful). If it has fewer, then the result is "undefined behavior", just as it is for unions or gross pointer kludgery. As for usefulness, I'll supply an anecdote. I once wanted to write unsigned int copybit(unsigned int x) { if (x & 0x10) x |= 0x40; else x &= ~0x40; return (x); } in such a way that the highly-optimizing compiler would generate a simple move-bit instruction appropriate to the architecture. An appropriate escape operator would have allowed me to write something like typedef struct { unsigned int :4, src:1, :1, dst:1; } hack; unsigned int copybit(unsigned int x) { escape(x, hack).dst = escape(x, hack).src; } which also exhibits the copy better than the original. Btw, it wouldn't have worked to write "*(hack *)&x" since the implementation passed arguments in registers; taking the address forced a store to memory. Nor could I use an intentional misdeclaration of the argument ("hack copybit(hack x)"), since the compiler didn't believe that struct types could be placed in a register. (Yes, I'm aware of all the portability problems in the above. For this application it didn't matter, as long as it worked.) But Doug actually said "sufficiently useful", and here I agree with him: it's not worth changing the existing language. "Fix it in `D'", as they say. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint Followups to comp.lang.misc.
pardo@cs.washington.edu (David Keppel) (09/02/89)
karl@haddock.ima.isc.com (Karl Heuer) writes: >[`copybit' should generate a simple move-bit instruction] >[I wanted to write] > unsigned int copybit(unsigned int x) { > if (x & 0x10) x |= 0x40; else x &= ~0x40; > return (x); > } >[Suggesting:] > typedef struct { unsigned int :4, src:1, :1, dst:1; } hack; > unsigned int copybit(unsigned int x) { > escape(x, hack).dst = escape(x, hack).src; > } >[Yes, I'm aware of the portability problems.] In cases such as this, GNU CC provides another solution: typed asm's that take variables as arguments. If you care, you can even put this function in to your .h file, qualify it with `inline', and away you go! #ifdef __GNUC__ unsigned int copybit (unsigned int x) { #ifdef __vax__ asm ("mumble %0,%1" : "=r" (x) : "0" (x)); #elseif defined (__machine__) ... #else { NEED A MACHINE TYPE! } /* Compile-time error. */ #endif return (x); } #else unsigned int copybit (..) {...} #endif ;-D on ( A void* warranty ) Pardo -- pardo@cs.washington.edu {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo
billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe,2847,) (09/02/89)
From karl@haddock.ima.isc.com (Karl Heuer): > An lvalue take-as operator is one of the few "universal escapes" that is > not provided by C, and is not easy to fake for the general case. (I > believe it's Modula-2 that has this feature as a builtin operator > named ESCAPE.) Actually, according to my Modula-2 manual (which is the "second, corrected edition"; I think there's now a "third, corrected edition"), Modula-2 provides type transfer functions which do not involve the generation of any machine instructions, and which carry the name of the type being converted to. Any representation differences between the two types would presumably have to be addressed via an encapsulating procedure which performed the necessary transformations. Ada provides Unchecked_Conversion, which essentially does the same thing except for the fact that any use of Unchecked_Conversion will immediately flag your program as potentially non-portable; standard type conversion functions exist carrying the name of the type which are guaranteed to be portable, but they only cover the predefined types. Modula-2 "second, corrected edition", doesn't seem to be overly concerned with identifying potential portability problems, although this may have been addressed in the "third, corrected edition". Bill Wolfe, wtwolfe@hubcap.clemson.edu
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/03/89)
In article <14500@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >Btw, it wouldn't have worked to write "*(hack *)&x" since the implementation >passed arguments in registers; taking the address forced a store to memory. That's in fact what I had in mind when I implied that C has existing tools that can do the job. The particular implementation didn't need to allocate actual memory for the operation; presumably it did so because its optimizer wasn't sufficiently clever. (I assume that this would have been coded as a macro, not as a function call.)