Currently we are developing a client/server application. In the client code we use a step sequence, performed by a switch/case. The code is working fine, but for me it's seems not quite right.
So here's the code.
while(true)
{
switch(sub_step_1){
case 1: /* Step 1: */
...
sub_step_1++;
break;
case 2: /* Step 2: */
...
sub_step_1++;
break;
case 3: /* Step 3: */
...
sub_step_1++;
break;
case 4: /* Step 4: */
...
sub_step_1=0;
break;
default:
return 0;
}
}
The step sequence is execute inside a function, and at the end it just returns to the main. Since everything works fine, I just wanted to ask if there is a possible way to optimize this sequence, espacially for debugging.
One thing that struck me as wrong is not so important, but your comment.
/* Step 3: */
is not step 3. it is actually step 1.
You dont go from switch case 1 to switch case 2 and so on because theres a break statement.
Just remove the sub_step_1 counter, then breaks, cases and switch, so your function becomes like this:
/* Step 1: */
...
/* Step 2: */
...
/* Step 3: */
...
/* Step 4: */
...
return 0;
Why not just have a sequence of function ?
step1();
step2();
step3();
step4();
Or simply sequential code if you don't want to pass the context.
Related
I want to write a c code to generate a pulse but cant seem to wrap my head around the logic to implement it. I come from a strong Verilog background & know how to do this in verilog(look for a change of state using xor & use that pulse, stretch it over time if needed by registering it multiple times)
How should I do this in C? I want to do something like
while(1)
{
switch(state)
case 0: // generate single pulse
case 1: // dont generate
case 2: // dont gererate
case 3: // generate single pulse
usleep(1000) // I want a 1ms pulse
}
state is modified by a code running on FPGA, so it changes depending on some logic.
Cant seem to thing of a way to do that. Some guidance will be appreciated
You need a slightly more powerful statemachine, which can do entry-actions.
Assuming
it is Ok for the state machine to be blind while pulsing
variable state changes inside your loop (e.g. being volatile and updated from ISR perhaps)
or state is updated somehow inside the loop (pseudo code for that is present)
You indicated in chat that you have some control over when the variable state changes. That is important. Either use the polling function updatestate(), which is called from a pseudo code line; or somehow make sure that the variable does not change between // enter protection ... and // leave protection ....
However, the statemachine will still be blind for changes between, especially during the usleep(1000);. If that is a problem, you need noticably more complex mechanisms.
Pseudo code proposal:
// somewhere before
volatile int state = 0; // somehow changing within the loop
int statecopy = 0;
int statebefore = state,
while(1)
{
// updatestate(); // if that is necessary
// Note that the state machine is blind for changes to state
// between executions of these initial lines.
// I.e. changes are noticed only when executing the update above
// or the critical section below this comment. (depending on how
// the variable state changes.
// enter protection for critical section
statebefore = statecopy;
statecopy = state;
// leave protection for critical section
switch(statecopy )
{
case 0: // generate single pulse
if (statecopy != statebefore)
{
// switch high
usleep(1000); // I want a 1ms pulse
// switch low
}
break;
case 1: // dont generate
break;
case 2: // dont gererate
break;
case 3: // generate single pulse
if (statecopy != statebefore)
{
// switch high
usleep(1000); // I want a 1ms pulse
// switch low
}
break;
default:
break;
}
}
You just need to implement little logic for state changing and action for each state, like this:
int state = 0;
while(1) {
switch(state) {
case 0: // generate single pulse
start_pulse();
usleep(1000);
stop_pulse();
break;
case 1: // dont generate , wait 1ms?
usleep(1000);
break;
case 2: // dont generate, wait 1ms?
usleep(1000);
break;
case 3: // generate single pulse
start_pulse();
usleep(1000);
stop_pulse();
break;
}
state = (state+1)%3; // next state: 0, 1, 2, 3, 0, 1, 2,...
}
To simplify the switch examples
switch( state ) {
case 1:
case 2:
usleep(1000);
break;
case 0:
case 3:
/* pulse high */
usleep(1000);
/* pulse low */
}
More is possible but probably not worth is, let the compiler figure it out.
i trying to write a Recursion function that get a decimal number and print the value in hexadecimal
but i dont know what worng in my code
please help me i still new in Recursion and dont get it complitly...
my code:
void PrintHexadecimalNumber(int n)
{
if (n%16==0)
return ;
PrintHexadecimalNumber(n/16);
switch ((n % 16))// A-F cases
{
case (10):
printf("A");
break;
case (11):
printf("B");
break;
case (12):
printf("C");
break;
case (13):
printf("D");
break;
case (14):
printf("E");
break;
case (15):
printf("F");
break;
}
if ((n%16)<10)
printf(n%16);
}
Your code isn't going to work because of the test you've written to stop the recursion.
if (n%16==0)
If you have the number (in hex) 10, the function will stop immediately because n % 16 will be 0. What you actually want to test for is when n is 0. Like this
if (n==0)
Your switch statement should also be expanded out to include the values 0 to 9 rather than having a separate if statement after it. You can group them together by leaving out the break
switch(n % 16)
{
/* existing case statements go here */
case 0:
case 1:
case 2:
...
case 9:
printf("%d",n % 16); // also fixing this as per comments above.
break;
}
Or you could just use printf("%x",n % 16) and do away with the switch completely if what you're trying to do is explore how recursion works.
Reviewing some 3rd party C code I came across something like:
switch (state) {
case 0:
if (c=='A') { // open brace
// code...
break; // brace not closed!
case 1:
// code...
break;
} // close brace!
case 2:
// code...
break;
}
Which in the code I was reviewing appeared to be just a typo but I was surprised that it compiled with out error.
Why is this valid C?
What is the effect on the execution of this code compared to closing the brace at the expected place?
Is there any case where this could be of use?
Edit: In the example I looked at all breaks were present (as above) - but answer could also include behaviour if break absent in case 0 or 1.
Not only is it valid, similar structure has been used in real code, e.g., Duff's Device, which is an unrolled loop for copying a buffer:
send(to, from, count)
register short *to, *from;
register count;
{
register n = (count + 7) / 8;
switch(count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n > 0);
}
}
Since a switch statement really just computes an address and jumps to it, it's easy to see why it can overlap with other control structures; the lines within other control structures have addresses that can be jump targets, too!
In the case you presented, imagine if there were no switch or breaks in your code. When you've finished executing the then portion of a if statement, you just keep going, so you'd fall through into the case 2:. Now, since you have the switch and break, it matters what break can break out of. According to the MSDN page, “The C break statement”,
The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.
Since the nearest enclosing do, for, switch, or while statement is your switch (notice that if is not included in that list), then if you're inside the then block, you transfer to the outside of the switch statement. What's a bit more interesting, though, is what happens if you enter case 0, but c == 'A' is false. Then the if transfers control to just after the closing brace of the then block, and you start executing the code in case 2.
In C and C++ it is legal to jump into loops and if blocks so long as you don't jump over any variable declarations. You can check this answer for an example using goto, but I don't see why the same ideas wouldn't apply to switch blocks.
The semantics are different than if the } was above case 1 as you would expect.
This code actually says if state == 0 and c != 'A' then go to case 2 since that's where the closing brace of the if statement is. It then processes that code and hits the break statement at the end of the case 2 code.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does Duff's device work?
I am trying to understand how this is working. Any help would be appreciated.
#include<stdio.h>
void duff(int count)
{
int n=(count+7)/8;
printf("n=%d count =%d\n",n,count%8);
switch(count%8){
case 0: do{ printf("case 0\n");
case 7: printf("case 7\n");
case 6: printf("case 6\n");
case 5: printf("case 5\n");
case 4: printf("case 4\n");
case 3: printf("case 3\n");
case 2: printf("case 2\n");
case 1: printf("case 1\n");
}while( --n >0);
}
}
main(){
int count;
scanf("%d",&count);
duff(count);
}
Basically if the switch case evaluates to case statement 2, then the do statment of the while is never executed. But i ran this program and it gave me the output, but unable to explain:
output:
3
n=1 count =3
case 3
case 2
case 1
This is known as duff's device and is used in code optimization techniques to reduce branch instructions. The reason that it works is that by default case statements without breaks fall through to the next case so when you hit case 3, you keep going through to case 2 and case 1.
Both the do and the case "statements" are essentially just "goto labels". They don't add any actual code. They just tell while and switch (respectively) where to jump to. In other words, there is no code for the do to (not) execute.
(That said, it is somewhat remarkable/bizarre that C's grammar allows cases to exist in children of the switch, rather just as direct children of a switch.)
There are no break statements between the cases so the cases fall through. Therefore n=3 causes case 3: case 2: and case 1: to be executed.
Given a simple switch statement
switch (int)
{
case 1 :
{
printf("1\n");
break;
}
case 2 :
{
printf("2\n");
}
case 3 :
{
printf("3\n");
}
}
The absence of a break statement in case 2, implies that execution will continue inside the code for case 3.
This is not an accident; it was designed that way. Why was this decisions made? What benefit does this provide vs. having an automatic break semantic for the blocks? What was the rationale?
Many answers seem to focus on the ability to fall through as the reason for requiring the break statement.
I believe it was simply a mistake, due largely because when C was designed there was not nearly as much experience with how these constructs would be used.
Peter Van der Linden makes the case in his book "Expert C Programming":
We analyzed the Sun C compiler sources
to see how often the default fall
through was used. The Sun ANSI C
compiler front end has 244 switch
statements, each of which has an
average of seven cases. Fall through
occurs in just 3% of all these cases.
In other words, the normal switch
behavior is wrong 97% of the time.
It's not just in a compiler - on the
contrary, where fall through was used
in this analysis it was often for
situations that occur more frequently
in a compiler than in other software,
for instance, when compiling operators
that can have either one or two
operands:
switch (operator->num_of_operands) {
case 2: process_operand( operator->operand_2);
/* FALLTHRU */
case 1: process_operand( operator->operand_1);
break;
}
Case fall through is so widely
recognized as a defect that there's
even a special comment convention,
shown above, that tells lint "this is
really one of those 3% of cases where
fall through was desired."
I think it was a good idea for C# to require an explicit jump statement at the end of each case block (while still allowing multiple case labels to be stacked - as long as there's only a single block of statements). In C# you can still have one case fall through to another - you just have to make the fall thru explicit by jumping to the next case using a goto.
It's too bad Java didn't take the opportunity to break from the C semantics.
In a lot of ways c is just a clean interface to standard assembly idioms. When writing jump table driven flow control, the programmer has the choice of falling through or jumping out of the "control structure", and a jump out requires an explicit instruction.
So, c does the same thing...
To implement Duff's device, obviously:
dsend(to, from, count)
char *to, *from;
int count;
{
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
If cases were designed to break implicitly then you couldn't have fallthrough.
case 0:
case 1:
case 2:
// all do the same thing.
break;
case 3:
case 4:
// do something different.
break;
default:
// something else entirely.
If the switch was designed to break out implicitly after every case you wouldn't have a choice about it. The switch-case structure was designed the way it is to be more flexible.
The case statements in a switch statements are simply labels.
When you switch on a value, the switch statement essentially does a goto to the label with the matching value.
This means that the break is necessary to avoid passing through to the code under the next label.
As for the reason why it was implemented this way - the fall-through nature of a switch statement can be useful in some scenarios. For example:
case optionA:
// optionA needs to do its own thing, and also B's thing.
// Fall-through to optionB afterwards.
// Its behaviour is a superset of B's.
case optionB:
// optionB needs to do its own thing
// Its behaviour is a subset of A's.
break;
case optionC:
// optionC is quite independent so it does its own thing.
break;
To allow things like:
switch(foo) {
case 1:
/* stuff for case 1 only */
if (0) {
case 2:
/* stuff for case 2 only */
}
/* stuff for cases 1 and 2 */
case 3:
/* stuff for cases 1, 2, and 3 */
}
Think of the case keyword as a goto label and it comes a lot more naturally.
It eliminates code duplication when several cases need to execute the same code (or the same code in sequence).
Since on the assembly language level it doesn't care whether you break between each one or not there is zero overhead for fall through cases anyways, so why not allow them since they offer significant advantages in certain cases.
I happened to run in to a case of assigning values in vectors to structs: it had to be done in such a manner that if the data vector was shorter than the number of data members in the struct, the rest of the members would remain in their default value. In that case omitting break was quite useful.
switch (nShorts)
{
case 4: frame.leadV1 = shortArray[3];
case 3: frame.leadIII = shortArray[2];
case 2: frame.leadII = shortArray[1];
case 1: frame.leadI = shortArray[0]; break;
default: TS_ASSERT(false);
}
As many here have specified, it's to allow a single block of code to work for multiple cases. This should be a more common occurrence for your switch statements than the "block of code per case" you specify in your example.
If you have a block of code per case without fall-through, perhaps you should consider using an if-elseif-else block, as that would seem more appropriate.