chris@umcp-cs.UUCP (07/17/86)
In article <2239@brl-smoke.ARPA> mangoe@mimsy.umd.edu (Charley Wingate) writes: >... I've been looking at 4.3 code, particularly for the Sun. There >are plenty of places where pointers are used indifferently as >pointers to structures and as pointers to arrays. If you mean `pointers to structures and pointers to arrays of those same structures', there is nothing wrong with that. The C memory model demands that an array be a linear arrangement of its components. If this is not true on a machine, that machine does not run C code. >There is code which relies on ints and pointers being the same size. Alas, this seems to creep in everywhere---usually as a result of programmer laziness. An imagined programming session: /* Oops, gotta call getenv, but the declarations are all way above. Enh, I won't bother declaring it. */ p = (char *) getenv("FOO"); First, this is bad coding, like writing unnecessary LOOPHOLEs in Mesa. Second, lint will complain. Third, it is not really all that hard to go put in the declaration. Leave out the cast and even the compiler will complain, which will remind you to go clean up! >There is code which relies on successive declarations being stored >contiguously and in order. Where? >Code which relies on NULL equalling zero is omnipresent. But NULL *must* equal zero. If you mean `the bit pattern of the null pointer-to-X equalling the bit pattern of the zero integer', again, this is bad coding, and again, lint will complain. >All this leads me inescapably to the conclusion that C was designed >to allow programmers to violate the rules which everyone else is >busily putting into their languages to protect themselves. In 1978 (or perhaps earlier, but the documentation says July 1978), Steven C. Johnson recognised the need for a type-checker for the C language. He wrote one. It is called lint. If you think type-checking is good, *use it*. If you just want your program to work on your Widget-brand computer, do whatever you like--- though you might still find lint useful. There are those who consider `lint' a necessary part of the C compiler, that the proper compilation command is lint file.c; cc file.c -o file These people never seem to worry about all the problems you describe. The C language has a good type-checker. It is just not built into the `normal' compiler. This may be a serious problem to some, but I have never found it to be so. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
chris@umcp-cs.UUCP (07/17/86)
In article <2446@umcp-cs.UUCP> I wrote: >In 1978 (or perhaps earlier, but the documentation says July 1978), >Steven C. Johnson recognised the need for a type-checker for the >C language. ... Ai! Make that `Stephen C. Johnson.' ---Or perhaps `S. C. Johnson', as it says in the documentation. My apologies for misspelling your name. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
greg@utcsri.UUCP (Gregory Smith) (07/17/86)
In article <2446@umcp-cs.UUCP> chris@maryland.UUCP (Chris Torek) writes: >>There is code which relies on ints and pointers being the same size. > >Alas, this seems to creep in everywhere---usually as a result of >programmer laziness. An imagined programming session: > > /* Oops, gotta call getenv, but the declarations are all > way above. Enh, I won't bother declaring it. */ > p = (char *) getenv("FOO"); > >First, this is bad coding, like writing unnecessary LOOPHOLEs in Mesa. >Second, lint will complain. Third, it is not really all that hard to >go put in the declaration. Leave out the cast and even the compiler >will complain, which will remind you to go clean up! > Fourth, it is not guaranteed to be portable. It will probably be a lot more portable than it should be, though. Compiler implementors have gone to surprising lengths to allow this sort of thing. From a code efficiency standpoint, for example, a 68000 should return int's in D0 and all pointer types in A0, which would break the above. ( Somebody pointed out that a certain 68K compiler has an option to return both types in *both* regs ). Or am I wrong, and there is a non-unwritten ( i.e. official ) rule that says everything should return in the same reg whenever possible? Imagine a library function ( coded in assembler ) which returns a useful int value if declared int and a useful, different, pointer value if declared as a pointer! ( not a serious suggestion, but would be feasible if the same code were given two names ). -- "You'll need more than a Tylenol if you don't tell me where my father is!" - The Ice Pirates ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
jdl@purdue.UUCP (Jon Loeliger) (07/30/86)
In article <3117@utcsri.UUCP>, greg@utcsri.UUCP (Gregory Smith) writes: > From a code efficiency > standpoint, for example, a 68000 should return int's in D0 and all pointer > types in A0, which would break the above. ( Somebody pointed out that a > certain 68K compiler has an option to return both types in *both* regs ). > Or am I wrong, and there is a non-unwritten ( i.e. official ) rule that > says everything should return in the same reg whenever possible? I am in the process of writing a 68000 backend and just this problem arose. As of now, I resolved it by postponing the critical decision, and left everything in D0 upon return. ------------------------------------------------------------------------------ Jon Loeliger I *think* these are my opinions, let me ask my boss... jdl@Purdue.ARPA Dept Computer Science jdl@Purdue.Edu W. Lafayette, IN 47907 jdl@mordred.cs.purdue.edu (317) 494-6180 {ihnp4, decvax, ucbvax, pur-ee}!purdue!jdl -- ------------------------------------------------------------------------------ Jon Loeliger I *think* these are my opinions, let me ask my boss... jdl@Purdue.ARPA Dept Computer Science jdl@Purdue.Edu W. Lafayette, IN 47907 jdl@mordred.cs.purdue.edu (317) 494-6180 {ihnp4, decvax, ucbvax, pur-ee}!purdue!jdl
cg@myrias.UUCP (Chris Gray) (07/31/86)
Jon Loeliger at Purdue writes that he needs to decide whether address results on a 68000 compiler should be in A0 or D0. Unfortunately, the best answer is probably obtained by looking at any code that you have to interface to - what does it do? I ran into the exact same problem while porting my Draco compiler to the Amiga. I planned to return address values in A0, so that they could be used directly if that's all the code called for. All of the AmigaDos and Kernal routines return all results in D0 however. This left me with three choices: have interface stubs move the result to A0; require very strange declarations and type cheating for the supplied routines; or have the compiler return pointers in D0 as well. For now I've chosen the third alternative, but I may eventually go back to the first. Chris Gray (..ihnp4!alberta!myrias!cg)
crowl@rochester.ARPA (Lawrence Crowl) (08/02/86)
In article <3117@utcsri.UUCP>, greg@utcsri.UUCP (Gregory Smith) writes: > From a code efficiency > standpoint, for example, a 68000 should return int's in D0 and all pointer > types in A0, which would break the above. ( Somebody pointed out that a > certain 68K compiler has an option to return both types in *both* regs ). > Or am I wrong, and there is a non-unwritten ( i.e. official ) rule that > says everything should return in the same reg whenever possible? Since there is no type checking between an external definition of a function and its actual definition, a programmer could implicitly type cast by listing the external definition with a different return type than the actual. If integers are put in D0 and addresses in A0, then the calling function would grab the return value from the wrong register. extern int f() ; BUT usage( ) { int i = f() ; } char *f() { return "ptr" ; } /* grabs from D0 */ /* puts in A0 */ So, the optimization would probably break some programs. -- Lawrence Crowl 716-275-5766 University of Rochester crowl@rochester.arpa Computer Science Department ...!{allegra,decvax,seismo}!rochester!crowl Rochester, New York, 14627
guy@sun.uucp (Guy Harris) (08/03/86)
> extern int f() ; > BUT > usage( ) { int i = f() ; } char *f() { return "ptr" ; } > /* grabs from D0 */ /* puts in A0 */ > > So, the optimization would probably break some programs. Those programs are already broken; it's just by pure luck that they happend to work on some C implementations. They also won't work on any C implementation where "sizeof(char *)" is different from "sizeof(int)"; nothing forbids such an implementation. "lint" will catch illegal code like the example above. It would be nice if compilers started giving warnings for using undeclared functions, and if the "a function can be implicitly declared as 'int' by usage" rule were deprecated by the ANSI standard. Lazily-written code that doesn't declare functions would still compiler under those compilers, and work as well as it did before (which may mean "work just fine" and may mean "not work at all"), but at least the programmer would be told that they may be doing something wrong. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
greg@utcsri.UUCP (Gregory Smith) (08/04/86)
In article <19880@rochester.ARPA> crowl@rochtest.UUCP (Lawrence Crowl) writes: >In article <3117@utcsri.UUCP>, greg@utcsri.UUCP (Gregory Smith) writes: >> From a code efficiency >> standpoint, for example, a 68000 should return int's in D0 and all pointer >> types in A0, which would break the above. ( Somebody pointed out that a >> certain 68K compiler has an option to return both types in *both* regs ). > >Since there is no type checking between an external definition of a function There is lint, which does this. >and its actual definition, a programmer could implicitly type cast by listing >the external definition with a different return type than the actual. If >integers are put in D0 and addresses in A0, then the calling function would >grab the return value from the wrong register. > >So, the optimization would probably break some programs. Very likely, but only incorrect ones. This 'implicit casting' is not legal C. It is much the same as passing an int to a function which expects a struct containing a single int - it will usually work, but if (when) it doesn't, the programmer is at fault. Would you call that 'implicit casting'? I assert that a 68K C implementation could be made which returns pointers in A0 and ints in D0, and no lintable program would be broken. (If this is not the case, then lint needs work :-) ) -- "You'll need more than a Tylenol if you don't tell me where my father is!" - The Ice Pirates ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg