cunniff@hpfclq.HP.COM (Ross Cunniff) (02/09/88)
For those of you who are using the Manx compiler (and perhaps for those of you using 16-bit ints with the Lattice compiler), here's a tip to help you avoid the Guru on machines with more that 512K. This really happened to a friend of mine (we spent an entire WEEKEND sorting this out; I would've seen it sooner, but Lattice promotes bad programming practices :-< ). Q. What's wrong with this program? #include <intuition/intuition.h> struct IntuitionBase *IntuitionBase; main() { IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", 33L ); JRandomIntuitionCall( .... ); } A. OpenLibrary is not declared explicitly as returning a pointer. This means that the compiler implicitly assumes that it is returning an int. On compilers which use 32-bit ints, this is no problem. If you are using 16-bit ints, this will Guru on a machine with $C000000 memory, but *NOT* on a stock 512k Amiga. Why? Well, since OpenLibrary returns an int (as far as the compiler knows), the compiler just uses the *lower 16 bits* of the return value when it stuffs it into IntuitionBase. This is just ducky on a 512K machine. It's not so nice on a machine with more. The solution? #include <intuition/intuition.h> struct IntuitionBase *IntuitionBase; main() { struct Library *OpenLibrary(); /* NOTE THE ADDITION OF THIS DECL! */ IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", 33L ); JRandomIntuitionCall( .... ); } (I believe that the Manx compiler has a header file that defines the return value of calls such as OpenLibrary; I think it may be called <functions.h>). Ross Cunniff Hewlett-Packard System Sofware Operation ...{ucbvax,hplabs}!hpda!cunniff cunniff%hplabs@hpda.ARPA
toebes@sas.UUCP (John Toebes) (02/19/88)
In article <4230019@hpfclq.HP.COM>, cunniff@hpfclq.HP.COM (Ross Cunniff) writes: > For those of you who are using the Manx compiler (and perhaps for > those of you using 16-bit ints with the Lattice compiler), here's > a tip to help you avoid the Guru on machines with more that 512K. > This really happened to a friend of mine (we spent an entire WEEKEND > sorting this out; I would've seen it sooner, but Lattice promotes > bad programming practices :-< ). > Q. What's wrong with this program? > #include <intuition/intuition.h> > struct IntuitionBase *IntuitionBase; > main() > { > IntuitionBase = (struct IntuitionBase *) > OpenLibrary( "intuition.library", 33L ); > JRandomIntuitionCall( .... ); > } > A. OpenLibrary is not declared explicitly as returning a > pointer. Under 4.0 (which supports short integers) the compiler will complain with error 101 whenever you do this. I have seen too many people get bit by this on the PC to let it happen on the Amiga with Lattice. The basic rule is that if you ever convert a 16 bit entity to a pointer *REGARDLESS OF ANY CAST* it will issue the error message. This will catch almost all of the errors of this type (only one it can't is if you do it through indirect pointers in a called subroutine or in assembler - but then again it isn't apparent from the source code anyway). There is also a compiler switch -cf that will have the compiler scream if you ever call anything for which there is no prototype. Personnaly, I always compile with the switch and demand that the compile proceed without warnings, but I like the compiler to find my errors instead of having to wait for the GURU to find them :-) /*---------------------All standard Disclaimers apply---------------------*/ /*----Working for but not officially representing SAS or Lattice Inc.-----*/ /*----John A. Toebes, VIII usenet:...!mcnc!rti!sas!toebes-----*/ /*------------------------------------------------------------------------*/
peter@nuchat.UUCP (Peter da Silva) (02/22/88)
In fact Manx will compain if you convert any scalar to a pointer, no matter what size it is. I suspect that this is only a problem for people who use Manx but turn off the warnings. They deserve whatever they get. The program listed, however, should have checked that IntuitionBase was properly opened. -- -- a clone of Peter (have you hugged your wolf today) da Silva `-_-' -- normally ...!hoptoad!academ!uhnix1!sugar!peter U -- Disclaimer: These aren't mere opinions... these are *values*.
fnf@mcdsun.UUCP (Fred Fish) (02/23/88)
In article <340@sas.UUCP> toebes@sas.UUCP (John Toebes) writes: >Under 4.0 (which supports short integers) the compiler will complain with >error 101 whenever you do this. I have seen too many people get bit by >this on the PC to let it happen on the Amiga with Lattice. The basic >rule is that if you ever convert a 16 bit entity to a pointer *REGARDLESS >OF ANY CAST* it will issue the error message. This will catch almost This really should be discussed on comp.lang.c, but I'd like to note that traditionally, a cast has been used to tell the compiler that the programmer really DOES understand what he is asking for, and what the expected results will be. In the example program given, the programmer obviously didn't understand that casting the result of the function call to a pointer, when the result was a short, didn't automatically magically turn the function into one that returned a 32 bit value rather than 16. Breaking the compiler to catch broken programs does not seem like the optimal solution. I could support generating a warning message here, but NEVER an error, and only generating a warning when the compiler was specifically requested to flag such questionable constructs. -Fred -- # Fred Fish hao!noao!mcdsun!fnf (602) 438-3614 # Motorola Computer Division, 2900 S. Diablo Way, Tempe, Az 85282 USA
fgd3@jc3b21.UUCP (Fabbian G. Dufoe) (02/29/88)
In article <707@mcdsun.UUCP>, fnf@mcdsun.UUCP writes: > In article <340@sas.UUCP> toebes@sas.UUCP (John Toebes) writes: > >Under 4.0 (which supports short integers) the compiler will complain with > >error 101 whenever you ... convert a 16 bit entity to a pointer *REGARDLESS > >OF ANY CAST* it will issue the error message. This will catch almost > > This really should be discussed on comp.lang.c, but I'd like to note that > traditionally, a cast has been used to tell the compiler that the > programmer really DOES understand what he is asking for, and what the > expected results will be. ... I could support generating a warning > message here, but NEVER an error ... Generally I would agree that a cast is the programmer's way of telling the compiler that he really understands what he is doing and wants to do it. However, pointers are a special case, I think. Trying to convert a 16 bit value to a pointer won't work if the memory pointed to has an address higher than FFFF. Since C doesn't let you control the actual memory addresses to which you might want to point you have no guarantee unless the machines doesn't have an address space larger than 64K. So it seems reasonable to me for the compiler to treat that as an error. Even if you write for a 64K machine (shudder) the goal of portability demands that you not cast shorts to pointers because it will break on any larger machines. Is there any way you can cast shorts to pointers in a way that won't break if you have enough memory? --Fabbian Dufoe 350 Ling-A-Mor Terrace South St. Petersburg, Florida 33705 813-823-2350 UUCP: ...gatech!codas!usfvax2!jc3b21!fgd3
kurt@tc.fluke.COM (Kurt Guntheroth) (03/04/88)
I used to think a cast was a way to unlock the type system in C too, but it turns out not to be. A cast is a type conversion operator and a cast can generate code. For instance, int foo; float bar; bar = (float) foo; should generate code to convert foo to a float. Furthermore, the result of a cast is an rvalue. That is why you can't always use casts on the left side of an assignment. Now, some compilers, like the BSD vax compiler permit this, but others, like the Sun compiler, do not. (Talking to Sun service is how I learned about casts.) There is a relevant chapter and verse in K&R too. Anyone remember where it is? Oh, by the way, this discussion has also been on comp.lang.c.
dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/04/88)
>generate code. For instance, > int foo; > float bar; > bar = (float) foo; >should generate code to convert foo to a float. Furthermore, the result of >a cast is an rvalue. That is why you can't always use casts on the left >side of an assignment. Now, some compilers, like the BSD vax compiler On the left side of an assignment? Yow! That isn't C. Still, if you want to cheat you can get around the automatic type conversion: int foo; float bar; bar = *(float *)&foo; /*sizeof(float) had better equal sizeof(int)*/ /*for this to work */ Believe it or not, I have seen people do this! Actually, this sort of thing is useful in certain cases. But I digress. As far as C goes, this is the deal with casts: (anycast)variable = variable; NOT LEGAL variable = &(anycast)variable; NOT LEGAL variable = (somecasts)&variable; LEGAL char c = *(char *)&bar; LEGAL. (USEFUL?) -Matt
scott@applix.UUCP (Scott Evernden) (03/06/88)
In article <8803032106.AA06910@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes: > > <CASTS> On the left side of an assignment? Yow! That isn't C. > I have done this kind of thing now and then, and I believe that it's legal C. I have not yet discovered a compiler that complains about this: struct point { int x, y; } p1, p2; struct rect { int x1, y1, x2, y2; } r; alpha() { * (struct point *) &r.x1 = p1; * (struct point *) &r.x2 = p2; } -scott
dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/07/88)
:In article <8803032106.AA06910@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
:>
:> <CASTS> On the left side of an assignment? Yow! That isn't C.
:I have done this kind of thing now and then, and I believe that it's
:legal C. I have not yet discovered a compiler that complains about this:
: * (struct point *) &r.x1 = p1;
: * (struct point *) &r.x2 = p2;
:}
:
:-scott
Sure, that works fine. What I meant was assigning something TO
a cast, ala: (long)x = 43; is what is illegal. One thing to remember
is that structure assignment is somewhat new in C, and thus not all compilers
have been upgraded to it yet.
-Matt
shimoda@rmi.UUCP (Markus Schmidt) (03/07/88)
In article <8803032106.AA06910@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
:
: (anycast)variable = variable; NOT LEGAL
: variable = &(anycast)variable; NOT LEGAL
:
: variable = (somecasts)&variable; LEGAL
:
: char c = *(char *)&bar; LEGAL. (USEFUL?)
:
Yeah, useful in some cases, but can be also dangerous if you
hit odd addresses for ints and longs.
So a char foo[4]= {\{1, 2, 3, 4};
b= *(int *)foo+1;
may give you (and gave me) the guru!
Cu
Markus
(shimoda@rmi.uucp)
dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/09/88)
>: char c = *(char *)&bar; LEGAL. (USEFUL?) >: >Yeah, useful in some cases, but can be also dangerous if you >hit odd addresses for ints and longs. >So a char foo[4]= {\{1, 2, 3, 4}; > > b= *(int *)foo+1; Yah, that's why I used *(char *) in my example. The proper way to cast to other types with possible alignment problems is to use a union, but you still have to be careful when overlaying structures on buffers (that caught me a couple of times!). -Matt