Spyke

Syndicated from the fediverse. Read and engage on the original instance.

View original on feddit.org

21 replies

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);
  }
}
63
Victorreply
lemmy.world

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.

5
scribe.disroot.org

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.

1
Victorreply
lemmy.world

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.

1

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;
}
3
lemmy.zip

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

17

probably just placeholder because what is actually assigned isn't relevant to the post

58
feddit.org

it's the easter egg operator. it assigns a random value to your variable. useful for when you need a quick source of good-enough randomness in computer games (/jk)

33

from what i could find "because it was designed that way"

For what it's worth, C23 has updated labels to allow being placed before declarations.

38
sik0fewlreply
piefed.ca

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.

16

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!"
9

When it's designed to be an expression

while (int x = 1) { ... Modify x to eventually be zero... }

That might make sense even if it looks weird. Kinda like a for loop.

5
fedinsfw.app

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

6

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;
}
4

You reached the end

can somebody confirm this pls? | Spyke