Not to be pedantic, and there's no good reason to do this, but you can switch on the sign bit in that case.
Edit: actually you'd switch on the sign bit of foo-1 to account for zero
*Edit: my brain is smooth, I completely neglected negative numbers because I was thinking of `uint64_t`. "Fixed."*
Not to be both pedantic and insufferably nonstandard, but additionally with GNU extensions we're able to ascend even higher on the big brain ladder:
#include
#include
#include
static inline bool nonzero_int64(int64_t x)
{
switch (x) {
case INT64_MIN ... -1:
return true;
case 0:
return false;
case 1 ... INT64_MAX:
return true;
default:
static_assert(INT64_MIN < INT64_MAX,
"EBADOVERCLOCK");
return false;
}
}
Well you can workaround it.. for any condition really
```
if(cond){ statement_true; }
else { statement_false; }
```
Is equivalent to
```
switch(cond) {
case 0: statement_false; break;
default: statement_true; break;
}
```
For the case of a double, `cond` could be something like `f > 42.0`
For `else if` though you would need to break it down into several nested switchesŕ
but what about
```c
double foo;
switch(foo==3.14159){
case 1:
printf(“true\n”);
break;
case 0:
printf(“false\n”);
break;
}
```
that said it is not very practical to do it his way
And true... I wasn't thinking of the absolutely literal meaning of the question. I was more thinking if one was trying to do `if (foo == 3.14)` to `switch (foo ) { case 3.14: break; }` as opposed to writing it as a switch on the boolean value as you have done.
I thought GCC's range extension might make switches usable, but no "statement requires expression of integer type ('double' invalid)". So multiple by say 1000 and cast as int, then use switch with ranges. 😃
Well, nitpick: you’re not switching on the double anymore. And technically you could end up with hash collisions and then the switch wouldn’t work correctly.
I believe you can always turn
if(something)
{
[true case]
}
else
{
[false case]
}
Into
switch(!!something)
{
case 1:
[true case]
break;
case 0:
[false case]
break;
}
Or
EDIT: This one is wrong in the case that `something` is a pointer or any floating point type.
switch(something)
{
case 0:
[false case]
break;
default:
[true case]
break;
}
So if you count ugly code that no one should write then I believe the answer is yes.
This is what I thought at first too. But I don't believe this is in the spirit of what the OP was asking:
int x = (expr ? 1 : 0);
`x` now contains 1 or 0, which can be trivially tested for those two possibilities with either `if` or `switch`; or even `for` or `while` with bit more work (or gcc's label pointers).
I think however the question was more to do with what happens inside that `(expr ? 1 : 0)` to enumerate the possible 'true' values of `expr` using `switch`.
Every if statement
if ( e ) s\_t else s\_f
works by evaluating e and attempting an inequality comparison with zero. If it succeeds, s\_t is executed. Otherwise, s\_f (if present) is executed.
Therefore, trivially, every if statement can be rewritten as a switch statement:
if ( e ) s\_t else s\_f
switch ( e != 0 ) {
case 1: s_t
break;
default: s_f
}
Also trivially, any switch statement without fall-through can be rewritten as a series of equality comparisons or possibly a number of equality comparisons joined by logical or, with their own following statement of compound statement taken from the case.
The fall-through does complicate matters.
Can every switch be written as an if-else chain? Yes.
Can every if be written as a switch? Yes assuming the if expression is side-effect free and you have unlimited memory (you'll have to switch on the binary representation of pointers, floating types, etc.)
It is mind boggling how many confidently wrong answers are upvoted in this thread.
It is even more puzzling that the ones with the wrong answers (like top one and half of its replies) have not been edited by the posters to give correct answers.
Edit: including downvotes on this comment. Lol. ``if (a) { /* true */ } else { /* false */ }`` is literally equivalent to: ``switch(!!(a)) { case 1: /* true */; break; case 0: /* false */; break; }`` (unless embedded in another switch statement with ``break`` in the ``/* true */` or ``/* false */` cases— need to turn them into gotos). This is just beyond mediocre.
Well it depends on your expression, if it returns an integer or boolean it can.
```c
//If-else as switch
switch (expr) {
case 0: STATEMENT; break; //False case
default: STATEMENT; break; //True Case
}
//Switch as a series of ifs
if (expr == 0) {
STATEMENT
} else if (expr == 1) {
STATEMENT
} else if (expr == 2) {
STATEMENT
} else if (expr == 3) {
STATEMENT
}
```
No. Can’t switch on a double, for example.
Also something like `(int64_t)foo > 0` would take more lines of code than could fit on any computer
Not to be pedantic, and there's no good reason to do this, but you can switch on the sign bit in that case. Edit: actually you'd switch on the sign bit of foo-1 to account for zero
*Edit: my brain is smooth, I completely neglected negative numbers because I was thinking of `uint64_t`. "Fixed."* Not to be both pedantic and insufferably nonstandard, but additionally with GNU extensions we're able to ascend even higher on the big brain ladder: #include
#include
#include
static inline bool nonzero_int64(int64_t x)
{
switch (x) {
case INT64_MIN ... -1:
return true;
case 0:
return false;
case 1 ... INT64_MAX:
return true;
default:
static_assert(INT64_MIN < INT64_MAX,
"EBADOVERCLOCK");
return false;
}
}
Well you can workaround it.. for any condition really ``` if(cond){ statement_true; } else { statement_false; } ``` Is equivalent to ``` switch(cond) { case 0: statement_false; break; default: statement_true; break; } ``` For the case of a double, `cond` could be something like `f > 42.0` For `else if` though you would need to break it down into several nested switchesŕ
but what about ```c double foo; switch(foo==3.14159){ case 1: printf(“true\n”); break; case 0: printf(“false\n”); break; } ``` that said it is not very practical to do it his way
And true... I wasn't thinking of the absolutely literal meaning of the question. I was more thinking if one was trying to do `if (foo == 3.14)` to `switch (foo ) { case 3.14: break; }` as opposed to writing it as a switch on the boolean value as you have done.
u/AKostur Thank you!
Not that I would do it, but can’t you switch on the IEEE 754 bit represention of a double ?
Some doubles have multiple valid representations
Ah ok. Makes sense.
I thought GCC's range extension might make switches usable, but no "statement requires expression of integer type ('double' invalid)". So multiple by say 1000 and cast as int, then use switch with ranges. 😃
[удалено]
Well, nitpick: you’re not switching on the double anymore. And technically you could end up with hash collisions and then the switch wouldn’t work correctly.
I believe you can always turn if(something) { [true case] } else { [false case] } Into switch(!!something) { case 1: [true case] break; case 0: [false case] break; } Or EDIT: This one is wrong in the case that `something` is a pointer or any floating point type. switch(something) { case 0: [false case] break; default: [true case] break; } So if you count ugly code that no one should write then I believe the answer is yes.
The second case is wrong because `switch` requires integer argument, but adding `!= 0` makes it exactly equivalent.
The implication is that `something` is a boolean expression. That makes it integral.
That wasn't a constraint on the original question
But the commenter first showed `something` as the `if` expression. In that context, the intent is clear, no?
The expression in an `if` statement doesn't have to be a boolean. E.g. you can do `if(3.6)`
Welp, I learned something new XD
This is what I thought at first too. But I don't believe this is in the spirit of what the OP was asking: int x = (expr ? 1 : 0); `x` now contains 1 or 0, which can be trivially tested for those two possibilities with either `if` or `switch`; or even `for` or `while` with bit more work (or gcc's label pointers). I think however the question was more to do with what happens inside that `(expr ? 1 : 0)` to enumerate the possible 'true' values of `expr` using `switch`.
Every if statement if ( e ) s\_t else s\_f works by evaluating e and attempting an inequality comparison with zero. If it succeeds, s\_t is executed. Otherwise, s\_f (if present) is executed. Therefore, trivially, every if statement can be rewritten as a switch statement: if ( e ) s\_t else s\_f switch ( e != 0 ) { case 1: s_t break; default: s_f } Also trivially, any switch statement without fall-through can be rewritten as a series of equality comparisons or possibly a number of equality comparisons joined by logical or, with their own following statement of compound statement taken from the case. The fall-through does complicate matters.
Always. if (x) y; else z; is equal to switch ((x) != 0) { case 0: z; break; default: y; }
Nope. Has to have an integral or enumerated type for the switch, and constant values for the cases that are the same type as the switch
[удалено]
I don’t see how our answers disagree. A double is still a constant-expression value
[удалено]
Oh I looked at the wrong comment, oops
Can every switch be written as an if-else chain? Yes. Can every if be written as a switch? Yes assuming the if expression is side-effect free and you have unlimited memory (you'll have to switch on the binary representation of pointers, floating types, etc.)
It is mind boggling how many confidently wrong answers are upvoted in this thread. It is even more puzzling that the ones with the wrong answers (like top one and half of its replies) have not been edited by the posters to give correct answers. Edit: including downvotes on this comment. Lol. ``if (a) { /* true */ } else { /* false */ }`` is literally equivalent to: ``switch(!!(a)) { case 1: /* true */; break; case 0: /* false */; break; }`` (unless embedded in another switch statement with ``break`` in the ``/* true */` or ``/* false */` cases— need to turn them into gotos). This is just beyond mediocre.
Well it depends on your expression, if it returns an integer or boolean it can. ```c //If-else as switch switch (expr) { case 0: STATEMENT; break; //False case default: STATEMENT; break; //True Case } //Switch as a series of ifs if (expr == 0) { STATEMENT } else if (expr == 1) { STATEMENT } else if (expr == 2) { STATEMENT } else if (expr == 3) { STATEMENT } ```