davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (09/27/89)
In the process of looking for a totally diferent problem, I generated the following program: main() { int i = 2; switch (i) { int j = 4; case 1: j += 4; break; case 2: case 3: case 'a': case 'b': j--; break; } } Note the initialization in the 4th statement. I was unable to find any compiler which generated working code for this initialization (although one did complain that the code was not reached). I tried Sun, Ultrix, Xenix and gcc compilers. This is an error in the compilers! As ugly as this is, the ANSI standard (3.1.2.4) says "If an initialization is specified for the value stored in the object, it is performed on each normal entry, but not if the block is entered by a jump to a label." I submit that executing a switch statement constitutes "normal entry" and that the initialization should be performed before evaluating the switch variable. Would any of the people still on X3J11 like to comment? Please let's not discuss the merits (or beauty) of this technique. Although I was in an attempt to find another compiler error, I can think of a few places where functional initialization would actually be useful. -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) "The world is filled with fools. They blindly follow their so-called 'reason' in the face of the church and common sense. Any fool can see that the world is flat!" - anon
kremer@cs.odu.edu (Lloyd Kremer) (09/28/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr)writes: >main() { > int i = 2; > switch (i) { > int j = 4; > case 1: j += 4; break; > case 2: > case 3: > case 'a': > case 'b': > j--; break; > } >} > >Note the initialization in the 4th statement. I was unable to find any >compiler which generated working code for this initialization (although >one did complain that the code was not reached). I tried Sun, Ultrix, >Xenix and gcc compilers. > >This is an error in the compilers! As ugly as this is, the ANSI standard >(3.1.2.4) says "If an initialization is specified for the value stored >in the object, it is performed on each normal entry, but not if the >block is entered by a jump to a label." > >I submit that executing a switch statement constitutes "normal entry" No, a switch statement is entered by a jump to a label. The jump is to any one of several places depending on which "case" is true, but an automatic initialization at the start of a switch statement is never performed. The variable is brought into scope within the switch block, but the initial contents of the variable are garbage. -- Lloyd Kremer ...!uunet!xanth!kremer Have terminal...will hack!
cpcahil@virtech.UUCP (Conor P. Cahill) (09/28/89)
In article <10041@xanth.cs.odu.edu>, kremer@cs.odu.edu (Lloyd Kremer) writes: > No, a switch statement is entered by a jump to a label. The jump is to > any one of several places depending on which "case" is true, but an automatic > initialization at the start of a switch statement is never performed. The > variable is brought into scope within the switch block, but the initial > contents of the variable are garbage. If this is the standard, I think it is broken. If the compiler allows a variable declaration, it should allow an initialization. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/28/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: >I submit that executing a switch statement constitutes "normal entry" >and that the initialization should be performed before evaluating the >switch variable. Would any of the people still on X3J11 like to comment? No, the block is the controlled part of the switch and it is entered via a case or default label, not sequentially starting at the block beginning. Declarations before the first label are valid, but no auto initialization is performed since execution does not "plow through" the declarations but instead bypasses them. The above is my understanding of what is supposed to be going on in a switch statement; my X3J11 notes are elsewhere at the moment.
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/28/89)
In article <1202@virtech.UUCP>, cpcahil@virtech.UUCP (Conor P. Cahill) writes: > If this is the standard, I think it is broken. If the compiler allows > a variable declaration, it should allow an initialization. If I recall correctly (my copy of the Standard is not at hand), you can specify the initializer but of course it won't be executed. Consider the following analogous case (which does NOT involve "switch") to see why: goto label; { int i = 4; foo(); label: bar(); baz(); }
dfp@cbnewsl.ATT.COM (david.f.prosser) (09/28/89)
In article <1202@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes: >In article <10041@xanth.cs.odu.edu>, kremer@cs.odu.edu (Lloyd Kremer) writes: >> No, a switch statement is entered by a jump to a label. The jump is to >> any one of several places depending on which "case" is true, but an automatic >> initialization at the start of a switch statement is never performed. The >> variable is brought into scope within the switch block, but the initial >> contents of the variable are garbage. > >If this is the standard, I think it is broken. If the compiler allows >a variable declaration, it should allow an initialization. The pANS specifies the way the C language works. Period. A switch statement is a multiway jump to a finite set of labels. If you jump into a block skipping over certain expressions, these expressions will not be executed. Similarly, if you skip over the code for initialization, it will not be executed. The allocation of automatic objects is a slightly different matter, so at least the objects are guaranteed to exist. The following example is copied from the pANS, section 3.6.4.2: Example In the artificial program fragment switch (expr) { int i = 4; f(i); case 0: i = 17; /* falls through into default code */ default: printf("%d\n", i); } the object whose identifier is i exists with automatic storage duration (within the block) but is never initialized, and thus if the controlling expression has a nonzero value, the call to the printf function will access an indeterminate value. Similarly, the call to the function f cannot be reached. There is nothing preventing a translator from warning that the code will not be reached, but it cannot refuse to compile fragments such as the above example. Dave Prosser ...not an official X3J11 answer...
scjones@sdrc.UUCP (Larry Jones) (09/29/89)
In article <561@crdos1.crd.ge.COM>, davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) writes [edited]: > switch (i) { > int j = 4; /* this initialization doesn't happen! */ > case 1: j += 4; break; > case 2: > } > > This is an error in the compilers! As ugly as this is, the ANSI standard > (3.1.2.4) says "If an initialization is specified for the value stored > in the object, it is performed on each normal entry, but not if the > block is entered by a jump to a label." > > I submit that executing a switch statement constitutes "normal entry" > and that the initialization should be performed before evaluating the > switch variable. Would any of the people still on X3J11 like to comment? Sure! If you look at Section 3.6.4.2 (The switch statement), you will find that: A switch statement causes control to jump to, into, or past the statement that is the switch body, depending on the value of a controlling expression, and on the presence of a default label and the values of any case labels on or in the switch body. Thus, a case statement is just a specialized form of goto and case labels are just that -- labels. You are not entering the body normally, you are jumping into it. Looking further in the same section shows an example which looks remarkably like yours with the explaination that the variable exists within the switch body, but is never initialized. ---- Larry Jones UUCP: uunet!sdrc!scjones SDRC scjones@SDRC.UU.NET 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 "I have plenty of good sense. I just choose to ignore it." -Calvin
cpcahil@virtech.UUCP (Conor P. Cahill) (09/29/89)
In article <11173@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: > In article <1202@virtech.UUCP>, cpcahil@virtech.UUCP (Conor P. Cahill) writes: > > If this is the standard, I think it is broken. If the compiler allows > > a variable declaration, it should allow an initialization. > If I recall correctly (my copy of the Standard is not at hand), you can > specify the initializer but of course it won't be executed. Consider > the following analogous case (which does NOT involve "switch") to see why: > > goto label; > { > int i = 4; > foo(); > label: bar(); > baz(); > } I still don't agree with this. One does not "conceptualize" the initialization as an execution. Since the code used to allocate the automatic variable on the stack is executed, the code used to initialize the variable should be executed. In addition the behavior is different if the declaration is "static int...". In that case the initialization does take place. What it the justification for the different behavior? -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
diamond@csl.sony.co.jp (Norman Diamond) (09/29/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr)writes: >>I submit that executing a switch statement constitutes "normal entry" In article <10041@xanth.cs.odu.edu> kremer@cs.odu.edu (Lloyd Kremer) writes: >No, a switch statement is entered by a jump to a label. Mr. Kremer, you start your reply with "No." So you think that correct execution of a switch statement constitutes abnormal entry to the block. I conjecture that very few will agree with you. Otherwise, it seems that both posters are correct. Executing a switch statement is both normal entry and a jump to a label. The standard is self-contradictory. -- Norman Diamond, Sony Corporation (diamond@ws.sony.junet) The above opinions are inherited by your machine's init process (pid 1), after being disowned and orphaned. However, if you see this at Waterloo or Anterior, then their administrators must have approved of these opinions.
bill@twwells.com (T. William Wells) (09/29/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:
: In the process of looking for a totally diferent problem, I generated
: the following program:
:
: main() {
: int i = 2;
: switch (i) {
: int j = 4;
: case 1: j += 4; break;
: case 2:
: case 3:
: case 'a':
: case 'b':
: j--; break;
: }
: }
:
: Note the initialization in the 4th statement. I was unable to find any
: compiler which generated working code for this initialization (although
: one did complain that the code was not reached). I tried Sun, Ultrix,
: Xenix and gcc compilers.
:
: This is an error in the compilers! As ugly as this is, the ANSI standard
: (3.1.2.4) says "If an initialization is specified for the value stored
: in the object, it is performed on each normal entry, but not if the
: block is entered by a jump to a label."
:
: I submit that executing a switch statement constitutes "normal entry"
: and that the initialization should be performed before evaluating the
: switch variable.
dpANS 3.6.1:
"labeled-statement:
identifier : statement
case constant-expression : statement
default : statement"
Case and default are *labels*.
dpANS 3.6.4.2:
"A switch statement causes control to *jump* to, into, or past..."
(Italics mine.)
Also, I believe that K&R explicitly says that this won't work.
---
Bill { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (09/29/89)
I guess my main thought on declarations at the start of a switch is that anything which is allowed (ie. legal C) should work. It would probably take less effort to make it work than to add error checking code, from a compiler standpoint. It a feature with limited use even if it did work, but I am bothered by anything I can write which is legal but may not work the same way on all implementations. Perhaps a little matter for the next committee would be to either say "initialization of variables declared at the start of a switch is not allowed" or "variables declared at the beginning of a switch are initialized before the control expression is evaluated, even if no cases are matched." I have no strong feelings about whether it should or shouldn't work, but it should be predictable. That's what standards are all about, right? -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) "The world is filled with fools. They blindly follow their so-called 'reason' in the face of the church and common sense. Any fool can see that the world is flat!" - anon
henry@utzoo.uucp (Henry Spencer) (09/30/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: > switch (i) { > int j = 4; > case 1: /* ... */ > >Note the initialization in the 4th statement. I was unable to find any >compiler which generated working code for this initialization... >(3.1.2.4) says "If an initialization is specified for the value stored >in the object, it is performed on each normal entry, but not if the >block is entered by a jump to a label." >I submit that executing a switch statement constitutes "normal entry"... Sorry, wrong. 3.6.4.2: "...control jumps to the statement following the matched case label..." Also note the example in 3.6.4.2, which explicitly makes the point that initializers in such a context are not executed. -- "Where is D.D. Harriman now, | Henry Spencer at U of Toronto Zoology when we really *need* him?" | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
walter@hpclwjm.HP.COM (Walter Murray) (09/30/89)
Concerning initialization of variables in a switch statement, please note that the dpANS only repeats what was spelled out in the original K&R: "Usually the statement that is the subject of a switch is compound. Declarations may appear at the head of this statement, but initializations of automatic or register variables are ineffective." Page 203. And the dpANS document does suggest this as a common situation for a warning: "A block with initialization of an object that has automatic storage duration is jumped into." Section A.5. Walter Murray -------------
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/30/89)
In article <1211@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes: >One does not "conceptualize" the initialization as an execution. Then one has the wrong mental model. Auto initialization is to all extents and purposes execution of an assignment statement. It therefore differs radically from static initialization, which is what your model fits.
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/30/89)
In article <637@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: >I have no strong feelings about whether it should or shouldn't work, but >it should be predictable. That's what standards are all about, right? The Standard specifies precisely what happens here. It is not implementation-dependent.
henry@utzoo.uucp (Henry Spencer) (09/30/89)
In article <637@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: >It a feature with limited use even if it did work, but I am bothered by >anything I can write which is legal but may not work the same way on all >implementations... If you want all legal constructs to work the same way in all implementations, you are in the wrong newsgroup! :-) C is *full* of things that are implementation-specific to some degree or other. The usual reason is that most programs don't care about characteristic X, but want the code to run fast, and pinning down characteristic X implies major speed loss on some machines. Actually, very few languages have the property you're after. At the very least, the detailed properties of floating-point arithmetic are almost always implementation-defined. And, as Doug has pointed out, ironically, the behavior of initializers at the head of a case is not an example of this sort of thing. Such initializers *do* *not* get executed in any conforming implementation. -- "Where is D.D. Harriman now, | Henry Spencer at U of Toronto Zoology when we really *need* him?" | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
ok@cs.mu.oz.au (Richard O'Keefe) (09/30/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: : In the process of looking for a totally diferent problem, I generated : the following program: : main() { : int i = 2; : switch (i) { : int j = 4; : case 1: j += 4; break; [much deleted] C has *always* worked like this. The body of a switch is a statement and the switch is a jump. Here's a really ugly piece of code I wrote to illustrate this once: main(argc) { switch (argc) if (0) case 1: printf("1\n"); else if (0) default: printf("not 1\n"); else printf("impossible\n"); exit(0); } "gcc -ansi -pedantic" still likes it! If you want initialised declarations, put the switch inside the block instead of the block inside the switch. A good C compiler ought to print a warning message about initialised declarations in a switch() body, but that's "quality of implementation".
barmar@kulla (Barry Margolin) (10/01/89)
In article <1989Sep30.052000.13719@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >And, as Doug has pointed out, ironically, the behavior of initializers at >the head of a case is not an example of this sort of thing. Such >initializers *do* *not* get executed in any conforming implementation. Well, since the initial value of automatic variables is undefined, a conforming implementation COULD execute them. A strictly conforming program cannot take advantage of this, though. Here's something I think is closer to the original poster's complaint: why does the standard permit initializers in declarations at the head of a switch body, if they are required to be ignored? If they were disallowed, then user's wouldn't be tempted to think they would be executed. The original poster postulated that it should be easy for implementations to initialize these variables, since it must allocate space for them. As was mentioned by several people in a different chain (which might have been in comp.lang.c), many C compilers allocate space for all the auto variables in a function when the function is entered; no actual allocation and deallocation takes place when entering and exiting internal blocks (this is possible because C doesn't allow variable-sized automatic arrays). Therefore, jumping to a label inside a block doesn't have to do any allocation. Thus, a compiler can treat a variable declaration with an initializer as if the declaration without the initializer were located in the outermost block (this is a simplification, as it ignores name conflicts) and the initializer were just an assignment statement. Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
blarson@basil.usc.edu (bob larson) (10/01/89)
>In article <1989Sep30.052000.13719@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >>Such >>initializers *do* *not* get executed in any conforming implementation. In article <30540@news.Think.COM> barmar@kulla (Barry Margolin) writes: >Well, since the initial value of automatic variables is undefined, a >conforming implementation COULD execute them. It COULD NOT execute any of the side effects the initializers have, however. A compiler that recognises this case should IMHO just give a warning. I have ported megabytes of net code to a machine that does not generate correct code for any declarations in a switch statement block, (code to adjust the stack is generated where it is never executed) and have found only one program where this is a problem. (C-kermit, the current beta has this fixed.) -- Bob Larson Arpa: blarson@basil.usc.edu Uucp: usc!basil!blarson
henry@utzoo.uucp (Henry Spencer) (10/01/89)
In article <30540@news.Think.COM> barmar@kulla (Barry Margolin) writes: >...why does the standard permit initializers in declarations at the head >of a switch body, if they are required to be ignored? ... In fact, one can read the C++ Reference Manual (as of Stroustrup's book -- haven't seen the latest one) as forbidding such initializers. While the section on switch has the same old C wording, the section on goto is quite firm that jumping past an initializer is forbidden. -- "Where is D.D. Harriman now, | Henry Spencer at U of Toronto Zoology when we really *need* him?" | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/01/89)
In article <30540@news.Think.COM> barmar@kulla (Barry Margolin) writes: >Well, since the initial value of automatic variables is undefined, a >conforming implementation COULD execute them. NO, not in general. (The only time it could occur is if it would have no observable effect! What would be the point of that?) >why does the standard permit initializers in declarations at the head >of a switch body, if they are required to be ignored? Because it's attempting to standardize C, not some vaguely similar language. The initializer IS NOT REQUIRED TO BE IGNORED. It is treated EXACTLY like any other auto initializer. Static initializers in a switch body are also treated like any other static initializers. You guys have the wrong mental model of C initialization!
chris@mimsy.UUCP (Chris Torek) (10/01/89)
In article <30540@news.Think.COM> barmar@kulla (Barry Margolin) writes: >Here's something I think is closer to the original poster's complaint: >why does the standard permit initializers in declarations at the head >of a switch body, if they are required to be ignored? It makes the language simpler conceptually: all variable declarations are of the form <type> <var> <optional initialiser> [, <var> <optional initialiser>]* ; Even a compiler that is only 1/3 decent% will warn about unreachable initialisers. Note that the <optional initialiser>s are, as Doug has already pointed out (it seems to require a great deal of repetition to get these to sink in), treated as though they were executable statements when they apply to automatic (as opposed to static or global) variables. ----- % 1/3: `less than half' -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
ok@cs.mu.oz.au (Richard O'Keefe) (10/01/89)
In article <19907@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes: > Even a compiler that is only 1/3 decent% will warn about unreachable > initialisers. I tried the following program (laid out to fit in two lines): main(argc) int argc; { switch (argc) { int i = 1; double x = 2.0; case 1: case 2: exit(i); default: exit(!!x); }} On a Sun-3/50 running SunOS 4.0.something cc: "line 1: warning: statement not reached" CC: "warning: statement not reached: case label missing" lint: "(1): warning: statement not reached" gcc: /* silence */ gcc -W: /* silence */ I suppose you *could* call this warning about unreachable initialisers, but calling them unreachable *statements* seems a little unhelpful. CC's message makes sense because C++ *would* allow a case label before the declarations (so the initialisers would be done sometimes!). Do I have permission to call gcc indecent now?
lawley@cs.mu.OZ.AU (michael lawley) (10/02/89)
On 1 Oct 89 14:32:00 GMT, ok@cs.mu.oz.au (Richard O'Keefe) said: > In article <19907@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes: >> Even a compiler that is only 1/3 decent% will warn about unreachable >> initialisers. > I tried the following program (laid out to fit in two lines): > main(argc) int argc; { switch (argc) { int i = 1; double x = 2.0; > case 1: case 2: exit(i); default: exit(!!x); }} > On a Sun-3/50 running SunOS 4.0.something > cc: "line 1: warning: statement not reached" > CC: "warning: statement not reached: case label missing" > lint: "(1): warning: statement not reached" > gcc: /* silence */ > gcc -W: /* silence */ I just ran the same code through "gcc -Wall -O". The -O causes gcc to do dataflow analysis etc. which it would otherwise not do. Here is the output: tt.c: In function main: tt.c:1: warning: return-type defaults to `int' tt.c:2: warning: implicit declaration of function `exit' tt.c:1: warning: `i' may be used uninitialized in this function tt.c:1: warning: `x' may be used uninitialized in this function tt.c:2: warning: control reaches end of non-void function Running with just "gcc -W -O" (for those of you who like sloppy code) gives tt.c: In function main: tt.c:1: warning: `i' may be used uninitialized in this function tt.c:1: warning: `x' may be used uninitialized in this function > I suppose you *could* call this warning about unreachable initialisers, > but calling them unreachable *statements* seems a little unhelpful. > CC's message makes sense because C++ *would* allow a case label before > the declarations (so the initialisers would be done sometimes!). These would seem to me to be much more useful error messages than the other compilers produce. > Do I have permission to call gcc indecent now? What about now?
karzes@mfci.UUCP (Tom Karzes) (10/03/89)
In article <561@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:
-This is an error in the compilers! As ugly as this is, the ANSI standard
-(3.1.2.4) says "If an initialization is specified for the value stored
-in the object, it is performed on each normal entry, but not if the
-block is entered by a jump to a label."
Switching into a block via a switch statement clearly consitutes entering
the block by a jump to a label. No code between the beginning of the block
and the case label should be executed, including dynamic initializations of
any automatic variables declared in the block.
msb@sq.sq.com (Mark Brader) (10/04/89)
Actually, there *is* a way to "normally enter" the switch body. Instead of entering the body by a jump from the switch header, you put a label on the body itself and jump to that! main() { int k = 0, m = 0; switch (m) bleagh: { int j = 4; case 0: printf ("%d\n", j); } if (k++ == 0) goto bleagh; } Assuming that the implementation doesn't trap on undefined values, this prints a garbage integer value, then 4. It would never have occurred to me to try this, if not for this discussion stream, and I can't dream of a sensible use for it. Isn't C wonderful? Only slightly less bizarre is to put one of the case labels ON the switch body rather than IN it -- 3.6.4.2 allows this and the compilers we have here support it -- whereupon you get initialization IF it is the first case that is chosen. For instance: initj() {printf ("initj() called\n"); return 4;} main() { int k; for (k = 0; k < 3; ++k) switch (k) case 1: { int j = initj(); default: printf ("%d\n", j); } } Assuming that the implementation doesn't trap on undefined values, this prints a garbage integer value, "initj() called", 4, and another garbage integer value. -- Mark Brader "I don't care HOW you format char c; while ((c = SoftQuad Inc., Toronto getchar()) != EOF) putchar(c); ... this code is a utzoo!sq!msb, msb@sq.com bug waiting to happen from the outset." --Doug Gwyn This article is in the public domain.
karzes@mfci.UUCP (Tom Karzes) (10/05/89)
In article <1989Oct3.184849.20106@sq.sq.com> msb@sq.com (Mark Brader) writes: >Actually, there *is* a way to "normally enter" the switch body. >Instead of entering the body by a jump from the switch header, you >put a label on the body itself and jump to that! >... >Only slightly less bizarre is to put one of the case labels ON the >switch body rather than IN it -- 3.6.4.2 allows this and the compilers >we have here support it -- whereupon you get initialization IF it is >the first case that is chosen. Note that although normal switch statement usage almost always involves a compound statement with all case labels at the top level within the compound statement, the syntax actually allows any statement. For example, the following: switch (x) case 5: case 9: foo(); if equivalent to: if ((t = x) == 5 || t == 9) foo(); where t is some temporary to avoid evaluating x more than once. Similarly, one might have: switch (x) case 2: if (y) default: foo(); else case 7: while (bar(z)) { case 12: baz(); case 13: z++; } Again, I'm not advocating any of this, I'm merely pointing out that it's within the definition of the language.
flaps@dgp.toronto.edu (Alan J Rosenthal) (10/13/89)
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) writes: >>>I submit that executing a switch statement constitutes "normal entry" kremer@cs.odu.edu (Lloyd Kremer) writes: >>No, a switch statement is entered by a jump to a label. diamond@csl.sony.co.jp (Norman Diamond) writes: >Mr. Kremer, you start your reply with "No." So you think that correct >execution of a switch statement constitutes abnormal entry to the block. >I conjecture that very few will agree with you. A point generally being missed in this discussion is that "normal entry" is a precise term. It is not just whatever method you personally usually choose to enter a block with a particular wrapper. It is the method of entering a block in general which is called "normal entry" by the standard. I can't find a definition of "normal entry", but I do find the following, 3.1.2.4, January 1988 draft: ... automatic storage duration. Storage is guaranteed to be reserved for a new instance of such an object on each normal entry into the block in which it is declared, or on a jump from outside the block to a label in the block or in an enclosed block. If an initialization is specified for the value stored in the object, it is performed on each normal entry, but not if the block is entered by a jump to a label. I think this is extremely clear. ajr -- Vs encr vf n xvaq bs frk, gura n chapu va gur zbhgu vf n xvaq bs gnyxvat.
karl@haddock.ima.isc.com (Karl Heuer) (10/13/89)
In article <10888@riks.csl.sony.co.jp> diamond@riks. (Norman Diamond) writes: >Mr. Kremer [seems to] think that correct execution of a switch statement >constitutes abnormal entry to the block. I conjecture that very few will >agree with you. I agree with him. `Normal' entry to a block is by falling into it from above. A block that happens to be the body of a switch is entered abnormally. This is not a contradiction. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
karzes@mfci.UUCP (Tom Karzes) (10/13/89)
In article <10888@riks.csl.sony.co.jp> diamond@riks. (Norman Diamond) writes:
->>I submit that executing a switch statement constitutes "normal entry"
->No, a switch statement is entered by a jump to a label.
-
-Mr. Kremer, you start your reply with "No." So you think that correct
-execution of a switch statement constitutes abnormal entry to the block.
-I conjecture that very few will agree with you.
-
-Otherwise, it seems that both posters are correct. Executing a switch
-statement is both normal entry and a jump to a label. The standard is
-self-contradictory.
For Pete's sake, this silly discussion was resolved long ago. Let it die.
The answer is very simple; you just don't like it. A switch statement
in C takes a single subordinate statement. It can be ANY statement. Any
case or default labels within that statement which are not associated with
a more closely nested switch statement are associated with that switch
statement. That's ALL you need to know to figure out the rest. Typical
use of a switch statement (and indeed the only use with which most people
are familiar) is to use a block as the subordinate statement, with all
case labels, and the default label (if present), at the top level inside
the block. In this case, execution of the switch statement causes a branch
into the block in the non-fall-through case, therefore the block is NOT
entered "normally" and any automatic initializations contained within
that block will be skipped. To do otherwise would be extremely unintuitive.
All kinds of special exceptions about entering blocks via a switch statement
would have to be added, and the implementation would be dreadful. If no
default label was present, the compiler would first have to evaluate the
expression and determine whether it matched one of the case labels. If
so, it would then have to branch to the start of the block and execute any
automatic initializations. Then it would have to actually branch to
the appropriate case label. It's an absurd proposal, and is extremely
unintuitive to anyone with even an average grasp of C. When I first
learned C many years ago, I didn't initially realize that switch
statements could take any type of subordinate statement, and in particular
that the subordinate statement could be a block that contained declarations,
some of which might be automatics with initializers. When I did learn about
this, it was OBVIOUS that executing the switch statement would blow right
past any such initializers. Perhaps what you really don't like is the
term "normal entry", because "abnormal entry" is somehow "bad", which
implies that typical use of a switch statement is "bad". Fine. Think of
it as "fall-through entry", or "normal-but-non-switch entry", or whatever
pedagogical aid seems appropriate to you. No one ever claimed that C was
an easy language for beginners. And please post any further speculation
as to how switch statements ought to be redesigned to comp.lang.misc.
The members of the ANSI committee weren't total morons, you know.
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/14/89)
In article <10888@riks.csl.sony.co.jp> diamond@riks. (Norman Diamond) writes: >Mr. Kremer, you start your reply with "No." So you think that correct >execution of a switch statement constitutes abnormal entry to the block. >I conjecture that very few will agree with you. You lose, then. The only use of the term "normal entry into a block" I could find in the Standard is in 3.1.2.4, where it is contrasted to a "jump from outside the block to a labeled statement in the block or in an enclosed block". The description of "switch" in 3.6.4.2 is quite explicit that a jump occurs, and that "case" and "default" are labels.
diamond@csl.sony.co.jp (Norman Diamond) (10/16/89)
Regarding the old, dead topic: >>>I submit that executing a switch statement constitutes "normal entry" >>No, a switch statement is entered by a jump to a label. >execution of a switch statement constitutes abnormal entry to the block. In article <1079@m3.mfci.UUCP> karzes@mfci.UUCP (Tom Karzes) writes: >For Pete's sake, this silly discussion was resolved long ago. Let it die. Yes. It died about two weeks after I submitted my posting. Last week I re-submitted five questions about the preprocessor. I thought that the original postings had gotten lost (a few weeks ago) in the maze of one little twisty news passage through kddlabs to the rest of the world. Before you criticize a poster for beating an old topic, why don't you look to see how long ago the submission was actually written? -- Norman Diamond, Sony Corp. (diamond%ws.sony.junet@uunet.uu.net seems to work) Should the preceding opinions be caught or | James Bond asked his killed, the sender will disavow all knowledge | ATT rep for a source of their activities or whereabouts. | licence to "kill".