ravi@flairvax.UUCP (06/15/83)
A very simple program
#include <stdio.h>
main ()
{
char *c[],*d[];
*c = "i am a string";
*d = "so what";
printf("%s\n",*c);
printf("%s\n",*d);
}
on 4.1bsd produced
so what
so what
whereas the C compiler on the TOPS-20 and other variations of the above
program on 4.1 bsd produced the correct result.
I am curious to find out WHY?.
ravi
Fairchild Research,
Palo Alto,CA.
kris@ur-valhalla.UUCP (Krzysztof Kozminski) (08/24/84)
Apparenly, cc compiler does not tolerate shifting unsigned values in initialization of global variables. Trying to compile the subroutine on the left produces the diagnostics: line 1: compiler error: expression causes compiler loop: try simplifying These are source files: bad.c good.c +-------------------------------------+---------------------------------------+ | int one = (((unsigned) 2) >> 1); | int ONE() | | int ONE() | { | | { | int one = (((unsigned) 2) >> 1); | | return one; | return one; | | } | } | +-------------------------------------+---------------------------------------+ However, after moving the declaration inside the subroutine as in the subroutine on the right, everything works OK. Unless I missed something, The Book does not forbid what I tried to do (actually, I tried to initialize something to a largest positive signed integer, i.e., complemented, unsigned zero shifted right by 1. After I got a similar error message, a couple of experiments determined a minimum expression causing the error). Lint also complains about the initialization: bad.c(1): illegal initialization Same thing happens when initializing static variables local to a procedure. Does anybody have an explanation/fix for this error message ? We run 4.1c BSD in case this matters (but the same thing occurs in 4.2). -- Krzysztof Kozminski {seismo,allegra,decvax}!rochester!ur-valhalla!kris
guy@rlgvax.UUCP (Guy Harris) (08/25/84)
> Apparenly, cc compiler does not tolerate shifting unsigned values in > initialization of global variables. Trying to compile the subroutine on > the left produces the diagnostics: > > line 1: compiler error: expression causes compiler loop: try simplifying > > | int one = (((unsigned) 2) >> 1); | int ONE() | I believe you are correct, and it is a compiler bug. I remember running into similar bugs in our 68K C compiler; casts are not always dealt with correctly in expressions evaluated at compile time. Unfortunately, I don't have a fix at hand. (Some routine which, in effect, evaluates casts at compile time is either not being called or isn't recognizing the cast as something it should clean up.) Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
chris@umcp-cs.UUCP (08/25/84)
It's obviously a compiler bug. More interesting is the code that comes out of the (4.2BSD) compiler: % /lib/ccom int one = (unsigned) 2 >> 1; [compiler output] .data .align 2 .globl _one _one: movl $1,r0 movl r0,-4(fp) movl -4(fp),r0 movl r0,-8(fp) movl -8(fp),r0 . . . It only happens with the typecasts; ``int one = 2 >> 1;'' works. ``int one = (char) 2 >> 1;'' generates a similar endless stream, but it begins differently: .data .align 2 .globl _one _one: movl $2,r0 movl r0,-4(fp) mnegl $1,r0 movl r0,-8(fp) movl -8(fp),r0 movl r0,-12(fp) . . . Obviously what's happening is this: during expression tree optimization, the compiler is trying to compute the value at RUNtime. However, as there are no free registers, it keeps sticking values into r0, finding out it can't get another free register, pushing r0 for safekeeping, getting the next number into r0, finding out it doesn't have a free register for the ``ashl'' operation, . . . . Things work if the operation is done inside {}s because there are some registers free. The bug is probably simply that the compiler is missing optimizations for expressions involving types other than `int' (and `long') for the ">>" and "<<" operators when both LHS and RHS are integer constants. (Both << and >> generate the endless stream of junk). (I wonder why the register allocation code doesn't scream loudly when asked for registers while code generation is off?) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
donn@utah-cs.UUCP (08/25/84)
To recap: The following program blows up the 4.2 (== System III?) C compiler: ------------------------------------------------------------------------ int one = (unsigned) 2 >> 1; ------------------------------------------------------------------------ The precise message you get is: ------------------------------------------------------------------------ "one.c", line 1: compiler error: expression causes compiler loop: try simplifying ------------------------------------------------------------------------ Chris Torek's observation is close to the mark (if not on it), but perhaps it's not as clear as it could be. The problem is that the initializer is not being reduced to a constant before the code generator receives it. If the code generator gets an expression, it goes ahead and generates the instructions needed to compute it; apparently it doesn't mind if it ends up generating instructions into data space, nor does it seem to care if any of the startup code for processing text has been run. The code generator can handle constant initializers (with a fake opcode of INIT) and that's it. More directly, what's happening is that when certain casts are transmuted into conversions, the compiler neglects to canonicalize the resulting trees. (Some casts get a second chance -- try substituting '+' for '<<' in the example and see what happens.) It's a fairly simple matter to ensure that makety(), the routine which does the transmutations, always canonicalizes the trees it returns. Here are the changes to /usr/src/lib/mip/trees.c: ------------------------------------------------------------------------ *** /tmp/,RCSt1008238 Sat Aug 25 06:30:16 1984 --- trees.c Sat Aug 25 04:37:26 1984 *************** *** 1061,1067 if( t & TMASK ){ /* non-simple type */ ! return( block( PCONV, p, NIL, t, d, s ) ); } if( p->in.op == ICON ){ --- 1061,1067 ----- if( t & TMASK ){ /* non-simple type */ ! return( clocal( block( PCONV, p, NIL, t, d, s ) ) ); } if( p->in.op == ICON ){ *************** *** 1079,1085 } } ! return( block( SCONV, p, NIL, t, d, s ) ); } --- 1079,1085 ----- } } ! return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); } ------------------------------------------------------------------------ I'm not sure that the first change is strictly necessary, but better safe than sorry. At any rate the sample program now compiles correctly. I don't think these changes have any nasty side effects -- I recompiled the compiler with the changes installed and it produced exactly the same binary as the old compiler did, for what it's worth. If the System V C compiler fixes this, I don't want to hear about it, Donn Seeley University of Utah CS Dept donn@utah-cs.arpa 40 46' 6"N 111 50' 34"W (801) 581-5668 decvax!utah-cs!donn
chris@umcp-cs.UUCP (Chris Torek) (08/26/84)
As long as we have people fixing bugs, how about someone patching up the pcc/ code that converts RS into LS and negates the shift? It fixes up constants but it doesn't remove double negations. Example: foo () { register int i,j,k; k = i >> -j; } produces (prettified) .align 1 .globl _foo _foo: .word 0xe000 mnegl r10,r0 mnegl r0,r0 ashl r0,r11,r0 movl r0,r9 ret What's the idea of the double mnegl? I got disgusted enough with this (and other similar but tougher-to-optimize) stuff in the output stage of my Versatec TeX filter that I stuck in asm()s (under #ifdef vax though). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
root@ur-valhalla.UUCP (08/27/84)
Well, I've installed Donn Seeley's fix for the C compiler screwing up on
initializing shifted, unsigned variables, and found out a nasty side effect:
The (unsigned) cast is IGNORED! This is my program:
main()
{ int big_number = ((~((unsigned) 0)) >> 1);
printf("this is a big number: %d\n",big_number);
}
Before installing the fix the program produced this output:
this is a big number: 2147483647
(To remind the original problem: should big_number be declared as static or
as a global variable, C compiler would blow up and go into a loop).
After installing the fix, I got the following output:
this is a big number: -1
Sigh....
--
Krzysztof Kozminski (truly sorry for not being able to fix the problem myself)
{seismo,allegra,decvax}!rochester!ur-valhalla!kris
mlr0@bunny.UUCP (Martin Resnick) (07/19/86)
Please try this code on your flavor of C compiler and see if you get the
correct results:
main()
{
int i;
i = 8;
i = i/2.5;
printf("i= %d\n", i);
i = 8;
i /= 2.5;
printf("i= %d\n", i);
exit(0);
}
The correct answer is 3 in both cases, not 4.
LINNDR%VUENGVAX.BITNET@WISCVM.ARPA (07/21/86)
I tried the i=i/2.5 vs. i/=2.5 program on two different compilers. The VMS/EUNICE compiler (essentially the BSD4.2 cc) gives 3 & 4; the VAX C (from DEC for VMS) gives 3 & 3. David Linn LINNDR@VUENGVAX.BITNET
3GTLJHW%CALSTATE.BITNET@WISCVM.ARPA (Joerg Hallbauer) (07/21/86)
I tryed your program on our PR1ME under both PRIMOS and PRIMIX and the result for both was the same: i=3 i=3 --Joerg
mp@allegra.UUCP (Mark Plotnick) (07/21/86)
The i /= f and i *= f bugs occur in the 4.3bsd-beta and 4.2bsd compilers (I don't know about pre-4.2). The bug is that the computation is done in integer rather than floating point. The 4.3bsd and System V VAX compilers do the right thing. We first noticed this bug on a 4.3bsd-beta system, when we saw "i *= 0.7" compile into "clrl _i". Incorrect code, but it's sure fast! Mark Plotnick allegra!mp
jrw@hropus.UUCP (Jim Webb) (07/22/86)
> Please try this code on your flavor of C compiler and see if you get the > correct results: . . . > The correct answer is 3 in both cases, not 4. I got 3 in both cases on my vax running System V Release 2. -- Jim Webb "Out of phase--get help" ihnp4!houxm!hropus!jrw
st94wb@sdcc12.UUCP (wade blomgren) (07/22/86)
I tried the '/=' bug test on the following: Pyramid 90x running 4.2/5.0 Unix (cc) - both answers == 3 (passed) SUN 2 running Unix 4.2 release 1.4 (cc) - answers == 3,4 (failed) Hmmmm... Wade Blomgren UCSD Academic Computing Svcs ....!sdcsvax!sdcc12!st94wb ....!sdcsvax!net1!wade
rlr@stcvax.UUCP (Roger Rose) (07/22/86)
I tried the program for V7 and 4.1 BSD compilers. On both compilers {int i; i=8; i = i/2.5;} gives i=3. {int i; i=8; i/=2.5;} gives i=4. -- Roger Rose UUCP: {hao ihnp4 decvax}!stcvax!rlr USnail: Storage Technology Corp. - MD 3T / Louisville, Co. 80028 phone: (303) 673-6873
brunner@sdsioa.UUCP (Rob Brunner X2830) (07/24/86)
> Pyramid 90x running 4.2/5.0 Unix (cc) - both answers == 3 (passed) > SUN 2 running Unix 4.2 release 1.4 (cc) - answers == 3,4 (failed) I ran the test on a Vax 11/750 running 4.2bsd cc and got 3,4 ... at least the bug isn't consistent across machines 8-). -- Rob Brunner email: Scripps Institution of Oceanography brunner@sdsioa.UUCP Mail Code A-010, UC San Diego sdsioa!brunner@sdcsvax San Diego, CA 92093 {backbone}!sdcsvax!sdsioa!brunner Phone: (619) 534-2040 (work) (619) 452-7656 (home)
stevesu@copper.UUCP (Steve Summit) (07/24/86)
In article <501@bunny.UUCP>, mlr0@bunny.UUCP (Martin Resnick) writes: > Please try this code on your flavor of C compiler... (followed by code demonstrating essentially > i = i/2.5; vs. > i /= 2.5; The answer is absolutely unequivocal on this point. A compiler that does not treat i=i/float and i/=float identically is broken, although many compilers are so broken. This question was discussed to death on the net a year or so ago. The discussion came to a screeching halt, quite unlike most net discussions, when the following article appeared from one dmr@research: > From: dmr@research.UUCP > Newsgroups: net.lang.c > Subject: bug in type conversion > Date: Wed, 4-Jan-84 21:32:17 PST > > Mike O'Brien points out that in the C compilers he has available, the > expression > i *= d; > where i is int and d is double is evaluated in fixed point, and > wonders why. The answer: it is a compiler bug. I fixed it in > (a post V7 version) of the 11 compiler, and it is fixed in the current > System V compiler (by "current" I mean the one I tried; > I don't know what is being shipped at this instant.) > > The manual is reasonably clear and unambiguous on the point, but > it's not surprising that people for search for definition problems when > the compilers are unanimously wrong. > > Dennis Ritchie What the manual says is (K&R page 191): "The behavior of an expression of the form E1 op= E2 may be inferred by taking it as equivalent to E1 = E1 op (E2); however, E1 is evaluated only once." The single evaluation of E1 is the only difference between the two forms; any type casting, including truncation, should be done exactly as if E1 = E1 op (E2) had been performed. Steve Summit tektronix!copper!stevesu
hugh@hcrvx1.UUCP (Hugh Redelmeier) (07/24/86)
In article <6224@allegra.UUCP> mp@allegra.UUCP (Mark Plotnick) writes: >The i /= f and i *= f bugs occur in the 4.3bsd-beta and 4.2bsd >compilers... The 4.3bsd and System V VAX compilers do the right thing. Well, not so fast. Many System V compilers (I don't know about 4.3BSD -- we haven't gotten it yet!) have a bug in the fix to this bug! Try "*p++ /= f;" where p is "int *": the ++ gets done twice. In fact, any side-effect on the left-hand-side would be done twice. Allen McIntosh of HCR has fixed this (with some effort) as part of our optimizer project (we produce a portable optimizer that fits into PCC and f77). Hugh Redelmeier (416) 922-1937 {utzoo, ihnp4, decvax}!hcr!hugh
jdptxt@adiron.UUCP (The Mad Hacker) (07/24/86)
The bug that is being discussed to death was in 4.1BSD as well. Somebody else ran into this problem a few months after I started programming professionally, and I gave him the solution to try i = i * 0.5 instead of i *= 0.5. I was told to never trust mixed-mode Fortran arithmetic and the Pascal that I worked with in college did not support float to integer conversions so I have stayed away from these 'op=' in mixed-mode. I always use them when possible otherwise. duke!adiron!jdp
rbutterworth@watmath.UUCP (Ray Butterworth) (07/25/86)
> > i = i/2.5; > vs. > > i /= 2.5; So, does anyone have a fix for this bug? I'll trade for a fix for a problem with void functions and the ?: operator. void f3(which) { extern void f1(),f2(); which?f1():f2(); } cc(1) gives an "incompatible types" error. In /usr/src/lib/mip/trees.c add the line indicated by "->>". This lets the above code lint and compile ok (and I don't think it causes any new problems). ... opact( p ) NODE *p; { ... switch( optype(o=p->in.op) ){ ... case COLON: if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); else if( mt12 & MDBI ) return( TYMATCH ); ... else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); ->> else if ( (!mt1) && (!mt2) ) return TYPL; break; case ASSIGN:
greg@utcsri.UUCP (Gregory Smith) (07/25/86)
>> Please try this code on your flavor of C compiler... >(followed by code demonstrating essentially >> i = i/2.5; >vs. >> i /= 2.5; > >The answer is absolutely unequivocal on this point. A compiler >that does not treat i=i/float and i/=float identically is broken, >although many compilers are so broken. This question was >discussed to death on the net a year or so ago... Well, I am definitely adding "(int) op= (float) and related things to my list of Things Not To Do If I Want To Make Life Easier. This can be considered "defensive programming". -- "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
ark@alice.UucP (Andrew Koenig) (07/26/86)
> So, does anyone have a fix for this bug? > I'll trade for a fix for a problem with void functions and the ?: operator. > > void f3(which) > { > extern void f1(),f2(); > which?f1():f2(); > } > cc(1) gives an "incompatible types" error. As it should. The only thing you're allowed to do with void values is throw them away.
ado@elsie.UUCP (Arthur David Olson) (07/27/86)
For those with source code, here's an addition to "lint" to generate warnings about float /= int and int /= float constructs. This is an addition to the 4.1BSD version of "lint/lint.c", in particular to the function "clocal"; your mileage will vary. As always, the trade secret status of the code involved precludes a clearer posting. The addition is conditioned on "OLDVERSION". ... NODE * clocal(p) NODE *p; { ... switch( o = p->in.op ){ #ifndef OLDVERSION case ASG MUL: if (pflag && p->in.right->in.op == SCONV) werror( "mixed-mode *= may surprise you"); break; case ASG DIV: if (pflag && p->in.right->in.op == SCONV) werror( "mixed-mode /= may surprise you"); break; #endif /* !OLDVERSION */ ... -- Lint is an Oscar Madison trademark. -- UUCP: ..decvax!seismo!elsie!ado ARPA: elsie!ado@seismo.ARPA DEC, VAX, Elsie & Ado are Digital, Borden & Ampex trademarks.
greg@utcsri.UUCP (Gregory Smith) (07/27/86)
In article <5858@alice.uUCp> ark@alice.UucP (Andrew Koenig) writes: >> So, does anyone have a fix for this bug? >> I'll trade for a fix for a problem with void functions and the ?: operator. >> >> void f3(which) >> { >> extern void f1(),f2(); >> which?f1():f2(); >> } >> cc(1) gives an "incompatible types" error. > >As it should. The only thing you're allowed to do with void values >is throw them away. But it is being thrown away. In e1?e2:e3, the contexts of e2 and e3 are inherited from the context of the ?: operator itself. In this case, that is in a 'for effect' or void context, so f1() and f2() should be treated as 'thrown away' too. -- "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
donn@utah-cs.UUCP (Donn Seeley) (07/27/86)
The 'i /= f' bug is fixed in 4.3 BSD. Someone (Hugh Redelmeier) stated earlier that this bug was fixed in System V but some implementations caused side effects in the left hand side to be duplicated. This was one of the problems that made the fix quite difficult for 4.3; the solution was fairly ugly but it works. Essentially what happens is that the compiler front end notices the special situation and avoids 'type balancing'; special code table entries enable the code generator to spot these trees and do the right thing. (This approach is properly termed 'hacking'.) I wasn't able to test this bug on our local System V boxen -- neither of them (SGI Iris, rev 3.4; HP-UX 5.0) have any form of the '/=' fix... The 4.3 compiler no longer generates an 'incompatible types' message for void expressions in the ':' part of a '?' expression -- it prints 'value of void expression used'! Will wonders never Cse, Donn Seeley University of Utah CS Dept donn@utah-cs.arpa 40 46' 6"N 111 50' 34"W (801) 581-5668 decvax!utah-cs!donn
rbutterworth@watmath.UUCP (Ray Butterworth) (07/28/86)
> > void f3(which) > > { > > extern void f1(),f2(); > > which?f1():f2(); > > } > > cc(1) gives an "incompatible types" error. > > As it should. The only thing you're allowed to do with void values > is throw them away. If I'm not throwing them away, what is it you think I'm doing with them? Also, the proposed ANSI draft explicitly states that the second and third operands of ?: may each have (void) type, so I'm not trying anything unusual here.
jcz@sas.UUCP (Carl Zeigler) (07/29/86)
In article <5858@alice.uUCp>, ark@alice.UucP (Andrew Koenig) writes: > > So, does anyone have a fix for this bug? > > I'll trade for a fix for a problem with void functions and the ?: operator > > > > void f3(which) > > { > > extern void f1(),f2(); > > which?f1():f2(); > > } > > cc(1) gives an "incompatible types" error. > > As it should. The only thing you're allowed to do with void values > is throw them away. Scan again, Andrew, the (void) values are being thrown away. -- John Carl Zeigler "Just once I'd like to meet an alien menace SAS Institute Inc. that wasn't impervious to bullets !" Cary, NC 27511 (919) 467-8000 ...!mcnc!rti-sel!sas!jcz
ark@alice.UucP (Andrew Koenig) (07/29/86)
> If I'm not throwing them away, what is it you think I'm doing with them? > Also, the proposed ANSI draft explicitly states that the second and third > operands of ?: may each have (void) type, so I'm not trying anything > unusual here. I think you're using them to form another value. It is irrelevant that you're then throwing that value away. Suppose f() is void and you say: f()+1; Now you're adding 1 to a void and throwing the result away. Should that be permitted? More seriously, I can actually see both sides of the argument. But the construction ...?f():g() where f() and g() are void is close enough to the edge that I wouldn't want to use it in any context where I might ultimately want to run it on a lot of compilers. Why not just say if (...) f(); else g(); ??
jsdy@hadron.UUCP (Joseph S. D. Yao) (07/31/86)
In article <461@watmath.UUCP> rbutterworth@watmath.UUCP (Ray Butterworth) writes: >> > void f3(which) >> > { >> > extern void f1(),f2(); >> > which?f1():f2(); >> > } >> > cc(1) gives an "incompatible types" error. >> As it should. The only thing you're allowed to do with void values >> is throw them away. >If I'm not throwing them away, what is it you think I'm doing with them? >Also, the proposed ANSI draft explicitly states that the second and third >operands of ?: may each have (void) type, so I'm not trying anything >unusual here. My 1984 version of X3J11 (has it been that long?) agrees with K&R that each of the operands must have a value. This makes intuitive sense. The meaning of X ? Y : Z is: an expression whose value is the value of Y, if the value of X is non-zero; otherwise, the value of Z. By this, all three must evaluate to some value. Do you have a more recent edition of X3J11 that r e a l l y lets voids in there? Ugh! (What date?) Besides which, all C compilers until just recently (Lattice, Microsoft) had been written to K&R and v7-s3-s5, not to the ANSI standard. -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP} jsdy@hadron.COM (not yet domainised)
whp@cbnap.UUCP (W. H. Pollock x4575 3S235) (07/31/86)
In article <134@sas.UUCP> jcz@sas.UUCP (Carl Zeigler) writes: > > > > void f3(which) > > > { > > > extern void f1(),f2(); > > > which?f1():f2(); > > > } > > > cc(1) gives an "incompatible types" error. > > > > As it should. The only thing you're allowed to do with void values > > is throw them away. > >Scan again, Andrew, the (void) values are being thrown away. The void values are not thrown away! Remember that (A?B:C) is an expression *returning a value*. C is giving the error because it can't determine the type of the return value. This is clearer in the following: void f3(which) { int f1(); void f2(); int foo; ... foo = which?f1():f2(); ... } which results in the same error message, for the same reason. Another example: f4() { ... return ((void) expression); } Note it doesn't mater what use is made of the return value (in the original example it is thrown on the floor, which is what probably confused some people).
aka@cbrma.UUCP (Andy Kashyap) (07/31/86)
In article <134@sas.UUCP> jcz@sas.UUCP (Carl Zeigler) writes: > In article <5858@alice.uUCp>, ark@alice.UucP (Andrew Koenig) writes: > > > So, does anyone have a fix for this bug? > > > > > > void f3(which) > > > { > > > extern void f1(),f2(); > > > which?f1():f2(); > > > } > > > cc(1) gives an "incompatible types" error. > > > > As it should. The only thing you're allowed to do with void values > > is throw them away. > >Scan again, Andrew, the (void) values are being thrown away. > No they are NOT; the value from the '?:' operator is being thrown away. The '?:' operator expects a non-void value so it can decide 'which' and pass the result to a higher level of expression (in this case there happens to be none). The complaint of "incompatible types" is the result of the '?:' operator expecting a non-void type as arguments and the arguments providing a void type. Wasn't that obvious from the diagnostics??? ;-) To re-phrase, the '?:' doesn't look at its operands (parameters or arguments) as function calls -- they might as well be 'f1()+5' or so -- but as expressions. Therefore it '*RETURNS THE VALUE* of one of its operands depending on the third'. A semantic point of view: A function call is an expression and can, therefore, be used anywhere an expression can be used. When you declare a function (void), you state that you intend to use that function as a statement instead, that you do not intend to use it in any operations. It can now only be used where a statement can. Keep in mind that an expression is a statement, but NOT vice-versa. If you look up the reference section of K&R, somewhere it says something like this (I don't have my K&R with me): ... expression -> expression ? expression : expression ... Thus you can not use a statement (ie (void) f1()) where an expression is expected. The BUG: there ain't none. The FIX: use 'if' instead. - andy kashyap -- +---------------------------------------------------------------------------+ : Jim, what's the value of Pi? : Andy Kashyap : : About 3.14159. Why do you ask, Doctor? : AT&T Bell Labs : : Actually, Captain, the exact value is 3.1415926535...: Columbus OH : : Kirk & McCoy: Shut Up, Spock!!! : ..!cbosgd!cbrma!aka: +---------------------------------------------------------------------------+
dbw@ariel.UUCP (DAVE B. WOOD) (08/01/86)
> construction ...?f():g() where f() and g() are void...
Don't forget side effects.
mikes@apple.UUCP (Mike Shannon) (08/05/86)
Just to be sure we're all on the same wavelength about void expressions with the ?: operator: Consider the case where you're writing a really complex #define macro, and you decide that you'd like some sort of IF statement in it, (take a look at getchar()). Can't you see a case where you might want to call a void function, and then set the value of the #define macro to be a side effect of the function? Sort of like #define foo(c) buffer_empty?fill_buff(),first_char_in_buf:first_char_in_buf I mean, it seems to me that the 'pro' argument is that you get flow of control in #define's. Although when you way that 'void things cannot participate in expressions', a rational person would say that conditional expressions are expressions and so you can't have a void thing in that kind of expression. -- Michael Shannon {apple!mikes}
ark@alice.UucP (Andrew Koenig) (08/06/86)
> Consider the case where you're writing a really complex #define macro, >and you decide that you'd like some sort of IF statement in it, >(take a look at getchar()). Can't you see a case where you might want to >call a void function, and then set the value of the #define macro to be >a side effect of the function? Sort of like >#define foo(c) buffer_empty?fill_buff(),first_char_in_buf:first_char_in_buf No problem using a void as the LHS of a comma operator, just as there's no problem using a void before a semicolon. Of course, you'd better parenthesize: #define foo(c) (empty?(fill(),first):first) Moreover, fill() probably returns a value you don't want to ignore, so maybe you should write it to return either the value of first or an error code. You can then write (empty?fill():first) which avoids the void issue altogether.
apc@cblpe.UUCP (Alan Curtis) (08/20/86)
In article <134@sas.UUCP> jcz@sas.UUCP (Carl Zeigler) writes: > > In article <5858@alice.uUCp>, ark@alice.UucP (Andrew Koenig) writes: > > > So, does anyone have a fix for this bug? > > > > > > void f3(which) > > > { > > > extern void f1(),f2(); > > > which?f1():f2(); > > > } > > > cc(1) gives an "incompatible types" error. > > > > As it should. The only thing you're allowed to do with void values > > is throw them away. > > >Scan again, Andrew, the (void) values are being thrown away. > No, the value of the statement is being thrown away, not the value of the void(s). Would you let me say: . . . f1() + f2(); . . Since I am throwing both away? Alan Curtis
guy@sun.uucp (Guy Harris) (08/21/86)
> No, the value of the statement is being thrown away, not the value > of the void(s). True, but one can imagine the ":" half-operator selecting between one of the two "void" values. One then throws away the value returned by the "?"/":" operator. > > Would you let me say: > . > . > . > f1() + f2(); > . > . > > Since I am throwing both away? No, you're not. You're adding them and then throwing the *sum* away. "void" "value"s can't be added. If you consider "void" to be a sort-of type, the set of whose values is a singleton set, then you can consider boolean_expression ? void_value_1 : void_value_2 to select one of the two "void" values and yield it as a result, so the ":" half-operator, unlike the "+" operator, can act on two "void" values. (Regardless of the value of the <boolean_expression>, the value yielded by the expression will be the same, since <void_value_1> == <void_value_2> == any other void value you can think of.) Think of it this way: "void" values require 0 bits to represent them, since the set of all such values has only one element. As such, "sizeof(void)" should be 0. As such, if you say void x; "x" takes up no memory. Given that, declaring objects of type "void" isn't very useful. An attempt to do so is probably an error, so it is rejected. Also, if objects of type "void" were implemented, most implementations would run the risk of giving it the same address as the next datum declared. So taking the address of a "void" is kind of useless, and so "void *" isn't useful as a true "pointer to void", so it can be overloaded. Also, since all "void" values are the same, an attempt to compare them is probably an error, so "==", etc. aren't defined over the set of "void" values either. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)