Programming in C I found out it was convenient in a switch-case to make little groups of cases by giving them the same name and add a number to it like:
case initiating:
break;
case (initiating+1):
break;
etc etc.
Currently I am still using brackets around around (initializing+1). But I wonder, do I have to do that?
would
case (initiating+2):
work?
I could not really find an anwser.
As you can see here a switch requires a constant expression. Every label should be known at compile time. Brackets are not required but can improve readability. Be sure that you really need (initiating + 2). 2 is a magic number and does not provide any additional information to the reader of your program. Using an enum will give you the same result but better readability.
The best way to verify if this works is by simply writing an example down and compiling it.
If initiating is a constant it should work.
Case labels are not required to be enclosed in parentheses, even if they are expressions containing arithmetic operations.
Related
In a program, I saw code like this (simplyfied):
switch (x){
case 1:
//dostuff
break;
/*___________________*/
//Here it is important
case 2:
default:
//dostuff
break;
}
Now I was wondering why someone writes a case and leaves it empty before the default case.
(Clearly it would make sense before another case).
I know that in C, there is a fallthrough if there is no break, so if x is 2, the program runs in the case 2: part, and directly falls through to the default-case.
So is the case 2:-case useless, since there is no code in it, and default will be done also without the label, so the same things are done with and without the case?
Is there a reason to write code like this (like easier modification when maintaining, but in my opinion not really relevant), or did the programmer just not remove it by mistake?
I have used switch several times in different languages, but never would have needed such code...
There is no reason for it. The explicit case 2 could be an attempt of writing self-documenting code, but here it doesn't really add anything, as the code lacks meaningful comments that explain what's unique with case 2.
Sometimes you could write code like this to explicitly document to the reader that you have considered all possible values that a variable can have. For example such self-documenting code might make sense with enums.
In this case, it really just looks like it is code still in development. Or it's some sloppily written left-overs that made it to the production code.
Last time I used MISRA C (embedded C rules for vehicles), all switch statements had to have a default clause. Potentially, this could be a reason for what you are seeing, as this would mean that ALL values passed into the switch would do something. Admittedly, that would mean the case 2 is redundant, but it might make things clearer when reading the code as a whole. It could also be some sort of embedded compiler optimisation (sometimes embedded compilers generate more efficient code when given a switch, rather than several ifs).
Are there any libraries out there that I can pass my .c files through and will count the visible number of, of example, "if" statements?
We don't have to worry about "if" statement in other files called by the current file, just count of the current file.
I can do a simple grep or regex but wanted to check if there is something better (but still simple)
If you want to be sure it's done right, I'd probably make use of clang and walk the ast. A URL to get you started:
http://clang.llvm.org/docs/IntroductionToTheClangAST.html
First off, there is no way to use regular expressions or grep to give you the correct answer you are looking for. There are lots of ways that you would find those strings, but they could be buried in any amount of escape characters, quotations, comments, etc.
As some commenters have stated, you will need to use a parser/lexer that understands the C language. You want something simple, you said, so you won't be writing this yourself :)
This seems like it might be usable for you:
http://wiki.tcl.tk/3891
From the page:
lexes a string containing C source into a list of tokens
That will probably get you what you want, but even then it's not going to be trivial.
What everyone has said so far is correct; it seems a lot easier to just grep the shit out of your file. The performance hit of this is neglagible compared to the alternative which is to go get the gcc source code (or whichever compiler you're using), and then go through the parsing code and hook in what you want to do while it parses the syntax tree. This seems like a pain in the ass, especially when all you're worried about is the conditional statements. If you actually care about the branches, you could actually just take a look at the object code and count the number of if statements in the assembly, which would correctly tell you the number of branches (rather than just relying on how many times you typed a conditional, which will not translate exactly to the branching of the program).
May be possible duplicate but couldn't have found the same.
Suppose I have following C code :
int a;
printf("Enter number :");
scanf("%d",&a); // suppose entered only an integer
// ignoring return value of scanf()
I got a case to check whether a is zero or non-zero.
if(a)
printf("%d is non-zero",a);
else
printf("%d is zero",a);
Everything is fine using if-else and I also know the other variations of if-else to achieve this . But problem comes with the switch-case as it says that we can implement everything in switch-case which we can do in if-else. But the following code fails.
switch(a)
{
case a:
printf("%d is non-zero",a);
break;
default:
printf("%d is zero",a);
break;
}
Also I know to reverse the case in the above code like this below will work and I will have my answer.
switch(a)
{
case 0:
printf("%d is zero",a);
break;
default :
printf("%d is non-zero",a);
break;
}
But the question is, Why ? Why if(a) is valid while case a: is not ? Is switch-case a compile time operation and if() run-time ?
The reason is that switch cases can be implemented as jump tables (typically using unconditional branch instructions). So they have to be resolved at compile time.
This makes them faster than ifs so it is better to use them when possible.
Case expressions must be constants. a is a variable, so it is not allowed. 0 is a constant, so that's fine. Only allowing constant expressions means that it is easier for the compiler to optimize the code.
The expression for the condition of an if statement has no such constraint.
As others have said, it's the way the language was defined.
If you have
int x, y, z;
int a;
... some code calculates x, y, z and a ...
switch(a)
{
case x:
.. do stuff here ...
break;
case y:
.. some more stuff ...
break;
case z:
... another bit of code ....
break;
}
the compiler can not figure out beforehand, at time of compilation where a should go if it's 1, 2, 3, 99, 465 or 5113212. So the code here is no more efficient than if we did
if (a == x) ... do stuff here ...
else if (a == y) ... some more stuff
else if (a == z) ... another bit of code
Further, what if x and y are the same value. Do we want BOTH do stuff and some more stuff to be executed, or just the one - and which one, the first or the second. What if the compiler re-orders the compares so that they are in a different order, because it's more efficient?
Switch is mainly intended for when you have a lot of choices of something, but each choice is known when you build the code. If that's not the case, you need something else.
Additional Information want to share Wiki
If the range of input values is identifiably 'small' and has only a few gaps, some
compilers that incorporate an optimizer may actually implement the switch statement as
a jump table or an array of indexed function pointers instead of a lengthy series of
conditional instructions. This allows the switch statement to determine instantly what
branch to execute without having to go through a list of comparisons.
It's a design decision by the creators of the language. IF case labels are constant, the compiler can optimize some cases by using a jump table. If they are not, the code will be equivalent to the multi-way if statement anyway, and the potential improvement goes away.
There is no problem defining a switch statement with variable case labels, or even different conditions for each branch, it is just that the designers of C didn't do that. Likely because they didn't see that as an advantage for the code they were writing.
The construct exists in other languages, like the COBOL I sometimes use. There it is not unusual to have a degenerated version like:
EVALUATE TRUE
WHEN x IS EQUAL TO 7
Do something
WHEN y IS LESS THAN 12
Do something else
WHEN z
Do yet another thing
END-EVALUATE
Here we have the if-else if-else chain masked as a switch (EVALUATE), which works by evaluating the conditions in order until it matches the first value.
In C the designers didn't want this, because it offers absolutely no performance advantage over the chained if-statements. On the other hand, if we require that all the conditions are constants...
Beyond the compile-time/jump-table problem, if and switch are not the same and even if case would accept a variable those two codes wouldn't have the same behavior. if body is evaluated if and only if the condition expression results in a non-zero value, while a case is entered if and only if the controlling expression and the label have the same value.
There is a big difference between if-then-else and switch statements, remember that breaks are not mandatory and execution falls through all the cases if nothing stops it. This behavior is really similar to a jump table, since inside a switch execution simply jump somewhere and goes on until it finds a break. However this use is rare, but it could be useful and easier to do than the if-then-else version.
The standard requires labels to be compile-time constants, and as other people already say, the idea behind it is a jump table for performance. Even if it's not mandatory (the C standard needs to be flexible), C99 rationale document seems to confirm this:
Case ranges of the form, lo .. hi, were seriously considered, but ultimately not adopted in the Standard on the grounds that it added no new capability, just a problematic coding convenience. The construct seems to promise more than it could be mandated to deliver:
A great deal of code or jump table space might be generated for an innocent-looking case range such as 0 .. 65535.
The range 'A' .. 'Z' would specify all the integers between the character code for
“upper-case-A” and that for “upper-case-Z”. In some common character sets this range
would include non-alphabetic characters, and in others it might not include all the
alphabetic characters, especially in non-English character sets.
Wikipedia has an article about jump tables.
I´m searching information about how to compare two codes and decide if the code submitted by someone is correct or not (based on a solution code defined before).
I could compare the output but many codes may have the same output. Then I think I must compare someway the codes and give a percentage of similitude.
Anybody can help me?
(the language code is C but I think this isn´t important)
Some of my teachers used online automated program grading systems like http://web-cat.org/
In the assignment they would specify a public api you must provide, and then they would just write tests against your functions, much like unit tests. They would intentionally pick tests that would exploit boundary conditions and other things students are notorious for not thinking about, and just call your code with many different inputs to try to get your code to fail.
Sometimes they would hardcode the expected values, other times they would allow values within a range, and other times they just did the assignment themselves and made it so your own code has to match the results produced by their code.
Obviously, not all programs can be effectively graded this way. It's also kinda error prone in that sometimes even the teacher made a mistake and overflowed an int or something, then the correct student submissions wouldn't match the teachers incorrect results. But, a system doesn't need to be perfect to be useful. But I think this raises an important point in that manually grading by reading the code won't necessarily reveal all mistakes either.
Another possibility is copy the submitted code, strip out all of the white space and search for substrings that must exist for the code to be correct and/or substrings that cannot exist for the code to be considered correct. The troublesome bit might be setting up to allow for some of the more tricky requirements such as [(a or c),((a or b) and c),((a or b) and c)], where the variables are the result of a boolean check as to if the substring related to the variable exists within the code.
For example, [("printf"),("for"), (not "1,2,3,4,5,6,7,9,10")], would require that "printf" and "for" be substrings in the code, while "1,2,3,4,5,6,7,9,10" i I'm not familiar with C, so I'm I'm assuming here that "printf" is required to be able to print anything without involving output streams, which could be accounted for by something like [("printf" or "out"),("for"), (not "1,2,3,4,5,6,7,9,10")], where "out" is part of C code required to make use of output streams.
It might be possible to automatically find required substrings based on a "correct" code, but as others have mentioned, there are alternative ways to do things. Which is why hard-coding the "solution" is probably required. Even so, it's quite possible that you'll miss a required substring, and it'll be marked as wrong, but it's probably the only way you can do what you ask with some degree of success.
Regular expressions might be useful here.
I am doing a stimulation of dead-code remover in a very simpler manner.
For that my Idea is to,
Step 1: Read the input C-Program line by line and store it in a doubly linked-list or Array.(Since deletion and insertion will be easier than in file operations).
Doubt:Is my approach correct? If so, How to minimize traversing a Linked-List each time.
Step 2: Analyzing of the read strings will be done in parallel, and tables are created to maintain variables names and their details, functions and their calls,etc.,
Step 3: Searching will be done for each entries in the variable table, and the variables will be replaced by its that time's value(as it has).
(E.g.)
i=0;
if(i==3) will be replaced by if(0==3).
But on situation like..
get(a);
i=a;
if(i){}
here,'i' will not be replaced since it depends on another variable. 'a' will not be replaced since it depends on user input.
Doubt: if user input is,
if(5*5+6){print hello;} ,
it surely will be unnecessary check. How can i solve this expression to simplify the code as
{
print hello;
}
Step 4: Strings will be searched for if(0),while(0) etc., and using stack, the action block is removed. if(0){//this will be removed*/}
Step 5:(E.g) function foo(){/**/} ... if(0) foo(); ..., Once all the dead codes are removed, foo()'s entry in the function table is checked to get no.of.times it gets referred in the code. If it is 0, that function has to be removed using the same stack method.
Step 6: In the remaining functions, the lines below the return statements (if any) are removed except the '}'. This removal is done till the end of the function. The end of the function is identified using stack.
Step 7: And I will assume that my dead-free code is ready now. Store the linked-list or array in an output file.
My Questions are..
1.Whether my idea will be meaningful? or will it be implementable? How
can I improve this algorithm?
2.While i am trying to implement this idea, I have to deal more with string
manipulations rather than removing dead-codes. Is any way to reduce
string manipulations in this algorithm.
Do not do it this way. C is a free-form language, and trying to process it line-by-line will result in supporting a subset of C that is so ridiculously restricted that it doesn't deserve the name.
What you need to do is to write a proper parser. There is copious literature about that out there. Find out which textbook your school uses for its compiler-construction course, and work through that -- or just take the course! Only when you've got the parser down should you even begin to consider semantics. Then do your work on abstract syntax trees instead of strings. Alternatively, find an already written and tested parser for C that you can reuse (but you'll still need to learn quite a bit in order to integrate it with your own processing).
If you end up writing the parser yourself, and it's only for your own edification, consider using a simpler language than C as your subject. Even though C at is core is fairly compact as languages go, getting all details of the declaration syntax right is surprisingly tricky, and will probably detract you from what you're actually interested in. And the presence of the preprocessor is an issue in itself which can make it very difficult to design meaningful source-to-source transformations.
By the way, the transformations you sketch are known in the trade as "constant propagation", or (in a more ambitious variants that will clone functions and loop bodies when they have differing constant inputs) "partial evaluation". Googling those terms may be interesting.