4 ms·
How this code can enter the "if (0)" part?
by xfennec 4y ago
How this code can enter the "if (0)" part?
- pcwalton 4y agoA switch can jump inside an if body that contains case labels, causing the condition not to be evaluated. C switch/case semantics are... not the most obvious.
- mark_undoio 4y agoBecause there's really a switch statement (hidden behind a macro) that will jump to labels within that block. The fact that the if condition is false means it won't just run the whole block straight through but you can still jump to a label in it. A goto statement would also allow you to jump into an otherwise-unreachable block.
- mtlmtlmtlmtl 4y agoARG_BEGIN opens a switch statement. So it can enter any of the cases, or it'll jump to the else if part.
- kreetx 4y agoIs there any reason this is not written as `switch(..) { <case statements>; default: <else statements> }`. I.e is there a reason for `if(0)`?
- jsmith45 4y agoThe whole `if` portion is for if the second character of the argument (after the initial `-`) is a second `-` [0]. In that case, the switch jumped to `case '-':` hidden within the macro, and the if statement is about processing long arguments (like `--help`). arguments only available as a short flag should never get executed as part of a short flag, so putting them inside the if(0) case is an easy option. An alternative without if(0) of any variety would be: ARG_BEGIN { if (ARG_LONG("reverse")) case 'r': { reverse = 1; ARG_FLAG(); } else if (ARG_LONG("input")) case 'i': { input = ARG_VAL(); } else if (ARG_LONG("output")) case 'o': { output = ARG_VAL(); } else if (ARG_LONG("help")) case 'h': case '?': { printf("Usage: %s [OPTION...] [STRING...]\n", argv0); puts("Example usage of arg.h\n"); puts("Options:"); puts(" -a, set a to true"); puts(" -b, set a to true"); puts(" -c, set a to true"); puts(" -r, --reverse set reverse to true"); puts(" -i, --input=STR set input string to STR"); puts(" -o, --output=STR set output string to STR"); puts(" -h, --help display this help and exit"); return EXIT_SUCCESS; } else { default: fprintf(stderr, "%s: invalid option '%s'\n" "Try '%s --help' for more information.\n", argv0, *argv, argv0); return EXIT_FAILURE; } break; case 'a': a = 1; ARG_FLAG(); break; case 'b': b = 1; ARG_FLAG(); break; case 'c': c = 1; ARG_FLAG(); break; case '\0': readstdin = 1; break; } ARG_END; The downside is that those few short flag only arguments no longer line up nicely with the others, and they come after the default, which could be a little bit confusing. Footnote: [0] Except if that second dash is the last character of the argument, in which case -- is the end of flags marker, meaning any further arguments that begin with `-` are just funky positional paramaters
- tempodox 4y agoThe `switch` statement in `ARG_BEGIN`.
- cesarb 4y agoThe way "switch" works in C is very weird. It behaves more like a "goto", where each "case ...:" is a label to which it can jump. So when the character is '-', it starts just before the "if (0)" (this part is hidden within the ARG_BEGIN macro), and as you noted, it will never enter that block. However, when the character is 'a', 'b', 'c', or nothing (the end-of-string marker), it will jump directly to the corresponding "case ...:" label, even though it's within that "unreachable" block.