all 21 comments

sorted by: hot top controversial new old
[–] 58 points 6 days ago

You actually shouldn't do this!

This doesn't introduce a new scope, so accidentally using x outside of the case block is UB. Instead you should introduce a new scope like so:

switch (foo)  {
  case BAZ: {
    int x = ...;
    foobar(x);
  }
}
  • source
  • [–] 19 points 6 days ago (4 children)
  • [–] 4 points 6 days ago (3 children)

    Is "case expr:" really a label? You could put anything in there, like "case 42:". I don't see a label, but maybe I don't know what a label is in C.

  • source
  • parent
  • hideshow 3 child comments
  • [–] 1 point 6 days ago (2 children)

    In C# it's certainly a label, it's the same syntax and you can also jump to them with goto, which is actually very convenient sometimes. As far as I know this is an ancient feature and seeing how early C# was mostly inspired by C, I would expect it to behave the same way there.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 5 days ago* (last edited 5 days ago) (1 child)

    What?

    If I have a case 42: in C#, I can issue a goto 42 and resume execution after that case? Or how would that work?

    From what I know, labels are only an identifier followed by a colon, like:

    stop: printf("stopped.\n");
    

    Or just the label and colon on one line and statements following on subsequent lines. I've never seen a switch case expression being called a "label". Very new to me. Would love to see a minimal demonstration example. 🙏

    Edit: huh, I guess you can.

  • source
  • parent
  • hideshow 1 child comment
  • Yes, you would do goto case 42;
    From MSDN:

    private static decimal CalculatePrice(CoffeeChoice choice)
    {
        decimal price = 0;
        switch (choice)
        {
            case CoffeeChoice.Plain:
                price += 10.0m;
                break;
    
            case CoffeeChoice.WithMilk:
                price += 5.0m;
                goto case CoffeeChoice.Plain;
    
            case CoffeeChoice.WithIceCream:
                price += 7.0m;
                goto case CoffeeChoice.Plain;
        }
        return price;
    }
    
  • source
  • parent
  • [–] 17 points 6 days ago (3 children)

    What does assigning ... do in C? Is that just default type value or something?

  • source
  • hideshow 3 child comments
  • [–] 11 points 6 days ago (6 children)

    question, why is a declaration not a statement?

  • source
  • hideshow 6 child comments
  • [–] 15 points 6 days ago (3 children)

    Possibly because declarations were originally not statements in C? You could only declare variables at the start of a function, but not assign them to something at the same time.

    Not sure why it still wouldn’t be allowed, though, especially if an empty statement can be a statement.

  • source
  • parent
  • hideshow 3 child comments
  • [–] 9 points 6 days ago

    I think it evolved like that:

    1. Declarations are separate entities to statements, because declarations do not translate to a machine code instruction
    2. Labels only make sense when attached to statements because they need to point to a particular machine code instruction <-- This should have been changed at least when declarations were allowed to be mixed with statements in compound statements
    3. Definitions are declarations plus an assignment, let's make them a subset of a declaration <-- I think this is the biggest mistake of them all
    4. "Well, it's already been that way for 40 years, too late to change it now!"
  • source
  • parent
  • [–] 7 points 6 days ago

    wonders of C

  • source
  • [–] 6 points 6 days ago (1 child)

    int x = ...; isn't just a declaration. Both are totally fine in most modern languages.

  • source
  • hideshow 1 child comment
  • [–] 2 points 5 days ago

    Can confirm. I have to do this all the time. Some coworkers just delete it, and I have to explain the situation every time when they see in the git blame that I put that semicolon there.

    As someone pointed out in another comment, in switch statements you should just start a new scope with {}. But in actual labels it's just better to put a load-bearing semicolon. You don't need to put it in another line though, I just put them like this:

    int main() {
        int *a = malloc(sizeof(*a));
        if (init_a(a) <= 0) {
            goto err;
        }
        do_something(a);
    err:;
        int ret = 0;
        if (a == NULL) {
            ret = -1;
        }
        free(a);
        return ret;
    }
    
  • source