13

I am new to Objective-C, But from all I know about switch statements, the following code should not print anything, because to me it seems that there should be a compilation error. However 2 is printed. I do not understand why. Could someone please explain?

- (void) test {
    int myVar = 2;

    switch (myVar) {
        case 1:
        {
            NSLog(@"result: %d", myVar);
            break;

            case 2:
            {
                NSLog(@"result: %d", myVar);
            }
            break;
        }
    }
}
Chirag Kothiya
  • 955
  • 5
  • 12
  • 28
Razor
  • 359
  • 2
  • 11
  • 9
    a `case:` is not a block or a stand-alone statement. It's a **label.** Think of it as the target of a conditional `goto`. – The Paramagnetic Croissant Nov 11 '14 at 15:49
  • 5
    Not sure why the downvotes. This is a very subtle detail of C that is interesting. Does this compile becuase it is valid code or by coincidence of the syntax? Also, go look up "Duff's device". – bbum Nov 11 '14 at 15:50
  • 1
    @bbum it's valid, exactly because `case`s are labels. Also, Duff's device. – The Paramagnetic Croissant Nov 11 '14 at 15:52
  • So `case 2:` is reachable because it is visible to the `switch` statement regardless of the scope brackets of `case 1:`? – Razor Nov 11 '14 at 15:55
  • I get that it is valid as pure scope & label. To rephrase; this appears to be one of the edge cases where the syntax allows a construct that really should be marked with a warning, at least, for the sake of programmer sanity, but can't. Duff's, at least, follows sane scoping patterns. – bbum Nov 11 '14 at 15:55
  • Those aren't "scope brackets". They don't define the scope in this case. They're simply decoration. In fact, you should be able to just add a bunch of `{}` in any case, and it will compile. `gcc -Wall` doesn't even complain. – nanny Nov 11 '14 at 15:56
  • 2
    Brackets must be used if a variable has to be declared in the body of `case:`. That is how I encountered this issue. My example is stripped to the core. – Razor Nov 11 '14 at 15:59
  • 2
    It's worth noting that this is not an Objective-C behavior. This behaves as shown in C as well. https://gist.github.com/wjlafrance/ce7581374a47ed65bf44 – wjl Nov 11 '14 at 16:01
  • @nanny, this decoration can control scope of variables. But it's dangerous of course, because you can define variable in case 1, and use it uninitialized in case 2. – Cy-4AH Nov 11 '14 at 16:01
  • 1
    _My example is stripped to the core_, .... As it should be. It presents the core of what is needed to convey the question well. – ryyker Nov 11 '14 at 16:12
  • 1
    Note this is not specific to Objective-C. This is pure C stuff. – i_am_jorf Nov 11 '14 at 16:25
  • With the later/latest versions of C, a variable can be declared almost anywhere, so the braces '{}' and no longer needed, So a variable declared inside a switch() statement can be declared anywhere – user3629249 Nov 11 '14 at 22:28

1 Answers1

13

You can think of the switch(value){case label:, ...} construct as a variable goto <label> statement, where:

1) switch(arg) determines which label execution will flow to next.
2) The key word case : defines the label. Example: case label:.

In a switch statement, the case key word is followed by a label (constant expression followed by a :), which is treated like the label used in goto statements. Control passes to the statement whose case constant-expression matches the value of arg in the statement switch(arg).

So legally there is nothing syntactically wrong with your code. That is, it will compile and build, and run just fine. The only thing the syntax in your example code violates is readability in that the execution flow ignores the block {...}, which in most cases would direct execution flow, and jumps directly to the targeted label defined by the case key word, just as it should.

It's not often that ignoring well established precedent to experiment with new hybrid constructs will yield useful results. But when it does, the results can become legendary. For example, see Duff's Device.

ryyker
  • 22,849
  • 3
  • 43
  • 87