#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
int n = 12;
int q = (n 3) / 4;
cout << q;
cout << ' ';
cout << n%4;
cout << ' ';
switch (n % 4) {
case 0: cout << n; cout << ' ';
do { n ; cout << n; cout << ' ';
case 3: n ; cout << n; cout << ' ';
case 2: n ;
case 1: n ; cout <<n; cout << ' ';
} while (--q > 0);
}
cout << n;
}
With the above code, I got the following:
3 0 12 13 14 16 17 18 20 21 22 24 24
I am not familiar with C language.
Why does it falls through in the second and third iteration of the while loop?
Does the switch case statement save the initial n%4 value and apply that during the do-while loop?
CodePudding user response:
case labels are just labels. Within your switch statement the code is executed sequentially because there is no jump statement as for example break, goto, or return.
To make it more clear you may rewrite the switch statement the following way when the expression n % 4
is equal to 0.
goto Label0;
{
Label0: cout << n; cout << ' ';
do { n ; cout << n; cout << ' ';
n ; cout << n; cout << ' ';
n ;
n ; cout <<n; cout << ' ';
} while (--q > 0);
}
So if you will run your program with the modification
#include <iostream>
using namespace std;
int main()
{
int n = 12;
int q = (n 3) / 4;
cout << q;
cout << ' ';
cout << n%4;
cout << ' ';
goto Label0;
{
Label0: cout << n; cout << ' ';
do { n ; cout << n; cout << ' ';
n ; cout << n; cout << ' ';
n ;
n ; cout <<n; cout << ' ';
} while (--q > 0);
}
cout << n; return 0;
}
you will get the same result.
3 0 12 13 14 16 17 18 20 21 22 24 24
If for example you will insert a break statement before the label case 2 like
switch (n % 4) {
case 0: cout << n; cout << ' ';
do { n ; cout << n; cout << ' ';
case 3: n ; cout << n; cout << ' ';
break;
case 2: n ;
case 1: n ; cout <<n; cout << ' ';
} while (--q > 0);
}
then this break statement in fact is inside the compound statement of the do-while statement. So the do-while statement will be interrupted and the control will be passed tp the point before the closing brace of the switch statement. So the switch statement also will be interrupted.
In this case the program output will be
3 0 12 13 14 14
CodePudding user response:
"Switch-cases" always fall through, unless you explicitly break
out of the switch.
The switch-case construct is essentially a glorified bunch of goto
s, but more robust than one constructed manually.
(Your code looks like a slightly mutated version of the legendary "Duff's device", a loop-unrolling construct that has confused generations of C programmers.)
Translated into unstructured "goto code", your switch is logically equivalent to
int x = n % 4;
if (x == 0)
goto zero;
if (x == 1)
goto one;
if (x == 2)
goto two;
if (x == 3)
goto three;
zero:
cout << n << ' ';
loop:
n ;
cout << n << ' ';
three:
n ;
cout << n << ' ';
two:
n ;
one:
n ;
cout << n << ' ';
if (--q > 0)
goto loop;
but the compiler might be able to create more efficient code from the switch than that series of conditionals, by using an actual jump table.
Footnote: gcc actually allows you to use labels as values and jump to them, so you could create exactly such a table yourself;
void* table = { &&zero, &&one, &&two, &&three };
goto *table[n % 4];
zero:
cout << n << ' ';
loop:
n ;
cout << n << ' ';
three:
n ;
cout << n << ' ';
two:
n ;
one:
n ;
cout << n << ' ';
if (--q > 0)
goto loop;
(Not that you should, but you could. A good compiler will compile your switch to something similar to this if it is beneficial, which it knows more about than a mere human.)