tim@unc.UUCP (Tim Maroney) (03/12/84)
The greatest advantages of C are its brevity and its generality. There is very little that you can't do in C, unlike other "general-purpose" programming languages such as Fortran and Pascal. However, there are some things that C can't do, at least not without postprocessing the assembly language output. That practice is A Very Bad Thing Indeed, since it tends to be very nonportable (some C compilers don't even produce assembly language! -- but that's obviously not the only reason for nonportability) and difficult for anyone except the person who wrote the code to understand. Furthermore, it makes assumptions about the format of the assembly code that may be invalidated by an intelligent optimizer. You can turn off the optimization in most such cases, of course, but then you are sacrificing performance. Now that an ANSI standard for C is in the works, people are putting forth their suggestions for "improving" C again. Most of these involve making it easier to do certain things that it is possible to do now (for instance, dynamically typed data like Pascal's variant records). I'm not interested in these very much, but I am interested in widening C's generality and thus ending once and for all this practice of assembly language postprocessing. The most common use of ALPP (as I'll call it for short) seems to be changing variable references into references to OS-specific objects such as device registers. In these cases, optimization is usually turned off as well, so that each time the object is referenced in C code a real reference is generated (instead of using modern register-optimization techniques). There was some discussion of this on this group a few months back, and the only "solution" I can recall was to introduce a new storage class specifier (one suggestion for its name was "volatile") for such variables. This solves only the problem of having to turn off optimization, though; you still have to do ALPP to give the references the proper name. A better solution would allow the C programmer to declare a certain identifier as being equivalent to an OS name, and the variable would implicitly be considerd volatile. Logically, the declaration is three-operand (type, identifier, OS name) rather than the normal C two-operand (type, identifier), so the syntax is a little problematic. One solution would be to disallow initialization of such variables, and put in the initialization field a string with the OS name; this would be consistent with the C practice of making code weird and hard to understand. :-> I'd like to hear (in this group rather than in mail) other suggestions for the syntax of this solution, or other solutions to the same problem. Another not-too-uncommon use for ALPP is global register declaration, that is, changing all references to an external variable to register references. This is useful in language interpreters (to use registers for function return values), and possibly in other applications as well. Syntactically, this is easy to solve; just allow the "register" storage class specifier at the external level. However, it presents some problems for the compiler when dealing with separately-compiled files, since the register used for each identifier must agree in all the object files. It would not be a good idea to defer this to the linker, since linkers typically perform only the function of filling in variable and function addresses; on some architectures, filling in register references is a significantly different task. I'd like to hear suggested solutions for this problem as well, also posted and not mailed. That about wraps it up for now. I'd like to hear other uses of ALPP and suggested solutions. I'd also like to know what "asm" is most commonly used for, again preferably with ways to eliminate its necessity or at least to clean it up. I'll leave you with about the only change I'd like to see in C that doesn't increase generality: string comparison operators. Ideally, these would just be "==", "<", ">", "<=", and ">=", but those already have meaning for strings (i.e., char *), that of pointer comparison. Either new operators or a new built-in data type would be needed. -- Tim Maroney, University of North Carolina at Chapel Hill mcnc!unc!tim (USENET), tim.unc@csnet-relay (ARPA) All opinions expressed herein are completely my own, so don't go assuming that anyone else at UNC feels the same way.
ka@hou3c.UUCP (Kenneth Almquist) (03/14/84)
One way to reference device registers without using assembly language is to use preprocessor defines like: #define reg (*(int *)0177430) Any C compiler that optimizes this sort of reference is likely to have problems with other types of C code, such as signal handlers. Kenneth Almquist
rcd@opus.UUCP (03/14/84)
<> The referenced article was mostly on the track of "there are some minor problems, but let's leave well enough alone..." But then... > I'll leave you with about the only change I'd like to see in C that doesn't > increase generality: string comparison operators. I wish this idea would die. It's often useful to look at the language material written by the authors of the language - it provides useful insights. From "The C Programming Language" by Kernighan & Ritchie (the blue and white book): Although the absence of some of these features may seem like a grave deficiency ("You mean I have to call a function to compare two character strings?"), keeping the language down to modest dimensions has brought real benefits. It's useful to realize that the authors not only though about string comparison operators; they decided at that time that they were not appropriate to the level or size of the language. Languages don't get "large" all at once. It happens a feature at a time. Sure, everybody likes the language, and it's really OK as is, but there's just this ONE thing that really ought to be changed...only nobody's "just one thing" is the same as anybody else's. And when it comes to standardization, remember that it's a long process even when everyone is in near-perfect agreement at the start. If you open up the just-one-thing bag, you'll still be waiting for a standard ten years from now. -- {hao,ucbvax,allegra}!nbires!rcd
stew@harvard.UUCP (Stew Rubenstein) (03/14/84)
While you're on the subject, what about == to compare two structures? This is even more reasonable, in that structure assignment is supported currently. Actually, I'd like to be able to do struct = 0; or struct = (struct foo) 0; to clear a structure but I realize that is a little more difficult. Still, if you special case 0 to represent an invalid pointer then special casing it to be a blank structure should not be too unpalatable. stew rubenstein {decvax,linus}!genrad!wjh12!harvard!lhasa!stew
tim@unc.UUCP (03/15/84)
There are some tricky issues involved in structure comparison, and there is no single best way to do it for all applications. The difficulty comes in when you have pointers as attributes (sorry, "members") of structures. You can do a standard quasi-numerical comparison on them, but that means that two pointers to different but equivalent objects will be considered unequal, which is not always what you want. On the other hand, if you descend into pointers, you will probably need to do it by user-invisible functions, which any true C hacker would gag at, and you run the risk of hitting a cycle in the structure and recursing until the stack overflows. The first method seems to be the only one tolerable; my question is, how usefiul would it be? Obviously, it would be good for complex numbers and a few other applications. What does everyone else think? Now about string comparison. After I suggested this, someone accused me of being insensitive to the perils of creeping featurism. I assure you that I am well aware of that problem; otherwise, I would have had a lot more suggestions. However, I don't think that extending comparison operators to apply to an existing data type, for which there is already a common ordering function known and often used, is really "adding" something -- it is just making the comparison operators more orthogonal. I would also support doing this in a more general way by allowing array comparisons when the array is of a comparable data type; the compiler can frequently generate more efficient code for this than the user easily can anyway. The big problem with all this is that there is really no such thing as arrays in C. There are pointers, but comparison is already defined for them. A smaller problem is that there are two types of (non)arrays which we'd want to compare: fixed-length and null-terminated. Can anyone come up with a clean solution for these problems? I would rather have just the string comparison than no extension of comparison at all, in any case. -- Tim Maroney, The Censored Hacker mcnc!unc!tim (USENET), tim.unc@csnet-relay (ARPA) All opinions expressed herein are completely my own, so don't go assuming that anyone else at UNC feels the same way.
rcd@opus.UUCP (03/16/84)
<> > While you're on the subject, what about == to compare two structures? > This is even more reasonable, in that structure assignment is supported... Yet another bad idea. This is much harder than it looks, for at least the following reasons: First, because of alignment constraints, structures may contain "holes" - space allocated but not used. Consider a 16-bit machine with a word alignment constraint on ints and struct {int a; char b; int c;} . . . In order to get both a and c aligned correctly, there's a one-byte hole after b (assuming typical allocation of fields). If the compiler is to generate code to compare two instances of these structs, it has to skip over the holes to avoid a spurious inequality result. (Remember that even though external variables can be initialized by the compiler - holes and all - automatic variables may not be and usually aren't because of cost.) A variant of the same problem occurs if the structure contains a union. There is no way to know which part of a union is currently in effect, so there's no way to know how much should be compared if the elements of the union do not have the same length. -- {hao,ucbvax,allegra}!nbires!rcd
ka@hou3c.UUCP (Kenneth Almquist) (03/18/84)
One thing that C lacks is a method of testing for arithmetic overflow. This makes it difficult to write efficient interpreters for "normal" languages that check for overflow. I suspect that many C programs sim- ply assume that overflow will not occur and produce incorrect results when it does occur. I don't have any good proposals for integrating such a facility into C. Kenneth Almquist
nather@utastro.UUCP (Ed Nather) (03/19/84)
<> Discussions of string comparison usually start with two assumptions that I believe are false: 1. A language is deficient if it lacks string comparisons; 2. They *could* be included, at modest cost in complexity. In the various C programs I have written that involve string comparisons, I find the ability to call a function to do exactly the right thing a real convenience. Sometimes I want to compare a substring to a string both of which are null-terminated; next time the substring may not be. Sometimes I want the pointer updated to point to the first character that didn't compare, sometimes not. I may want the *second* appearance of a substring rather than the first or last. If every possible option were included as part of a language the cost in complexity would not be modest -- and I'd never remember all the options. Alternatively, if only the basic, vanilla comparisons are included, it won't do what I want, I'll have to write a function call anyway, then explain in a comment why I had to do it that way, fuming all the while. After all this, an opinion: Leave the string comparisons OUT. -- Ed Nather ihnp4!{ut-sally,kpno}!utastro!nather Astronomy Dept., U. of Texas, Austin
hamilton@uiucuxc.UUCP (03/19/84)
#R:unc:-692200:uiucuxc:21000009:000:419 uiucuxc!hamilton Mar 18 23:04:00 1984
phil@unisoft.UUCP (Phil Ronzone) (03/20/84)
>> <> >> > While you're on the subject, what about == to compare two structures? >> > This is even more reasonable, in that structure assignment is supported... >> Yet another bad idea. This is much harder than it looks, for at least the >> following reasons: .... However -- comparing two structure of identical names is useful. Tells the compiler to do byte-for-byte compare inline. Equality and inequality are obvious, but I wouldn't want to count on < or >. Just to provoke net.lang.c.flame, how about my favorite extension to C? break(expr);
rcd@opus.UUCP (03/20/84)
<> Articles suggesting string comparison in C so far have addressed the issues of "does it belong there?" and such. A very different issue is that the correct string-comparison algorithm is anything but obvious. Using the native collating sequence - even in the ASCII part of the world - is only a primitive solution. Text can seldom be compared "reasonably", in terms of human expectations, with the ASCII ordering. For one thing, "dictionary order" is different from ASCII, since it regards case of letters as less significant than differing letters. Comparisons of names present another problem (and a messy one) - you have to get Mc and Mac together, etc. Then there's the language problem - for example, in Spanish "ll" and "ch" are treated as single letters. Probably the situations in which the native collating sequence is correct are limited to numeric comparisons (integers only, of course) and general string comparisons where ANY order is OK as long as it satisfies the rules of an ordering relation - as in searching, building ordered trees, etc. -- {hao,ucbvax,allegra}!nbires!rcd
aaw@pyuxss.UUCP (Aaron Werman) (03/20/84)
Here is a neologism that I had wanted to add to C back in the seventies, when C wasn't considered the next COBOL: add a GENSYM to the preprocessor (you know, that macro in LISP/assemblers that creates a new, different identifier whenever invoked, allowing harrowing language additions) I shudder to think of it now, when it it is considered a reasonable applications development language. {harpo,houxm,ihnp4}!pyuxss!aaw Aaron Werman
guy@rlgvax.UUCP (Guy Harris) (03/20/84)
>> <> >> > While you're on the subject, what about == to compare two structures? >> > This is even more reasonable, in that structure assignment is supported... >> Yet another bad idea. This is much harder than it looks, for at least the >> following reasons: .... > However -- comparing two structure of identical names is useful. Tells the > compiler to do byte-for-byte compare inline. Equality and inequality are > obvious, but I wouldn't want to count on < or >. You missed his point; to correctly compare two structures a byte-for-byte comparsion should *not* be done. The bytes which are not part of structure members, but which are just padding to put structure members on the right boundary, *must* not be compared or two structures which "should" be equal won't compare equal. Yes, the comparison would be nice, but it's not trivial to implement and won't compile into a simple comparison. Also, < and > are flatly impossible; what about struct complex { double realpart; double imagpart; }; Any result of < and > would be misleading as the complex numbers aren't an ordered field. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
eric@wucs.UUCP (Eric Kiebler) (03/22/84)
[And down in the lovely muck I've lain; Happy -- 'til I woke again!] For a good example of "lets give each function name an infix operator", look at Icon. That language is Martian. Powerful, but Martian nonetheless. It is the kind of language you will like if you like that kind of language. We could always drag APL through the dirt, but it's supposed to look like that. Has anyone out there developed any packages of macros or preprocessors to add abstract data types to C? Was it worthwhile if so? Has anyone out there used PPI's objective-C? How about class-c from Always Talking and Talking? eric -- ..!ihnp4!afinitc!wucs!eric
grunwald@uiuccsb.UUCP (03/27/84)
#R:unc:-690000:uiuccsb:9000017:000:626 uiuccsb!grunwald Mar 26 09:13:00 1984 On the subject of language features: Why not take a step into the seventies and introduce abstract data types to the language? I understand that a version of Bell internal C does this already. Then, as in CLU and Ada, your cluster/package specification allows you to define equality, similarity, orderings, assignment etc. This eliminates the need for the "string" type and string operations proposed, the structure equality question would be simpler and, if you design it properly, you could propably even implement structured assignment as suggested. It seems to be the most general tool to solve a plethora of problems.