Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I know the differences between i++ and ++i (like this) if I want to use their new values. And I saw many examples in The C Programming Language (K&R) use expressions like s[i++] = c;. Sometimes, I come across codes (shown following) make me confused and this style seems highly regraded by them.
while (*string1++ = *string2++); //in c
And in this post, Jon 'avoid using' this style.
So my question is to use i++ (or ++i) like above code a good practice? If not, in which situation should I use it (Just when I don't use its new valve ?)
By itself, i++ is a clear, idiomatic expression for the idea of incrementing a variable. By itself, it is as clear as it gets. A computer language was named after this idiom (C++).
Jon wasn't saying to avoid "i++"; he was saying to avoid combining it with other expressions that would complicate things, where the increment operation was a "side effect". Like:
arr2[++j] = arr[++i]; // now what the heck is going on? I have to stop and look.
In that case, it is more reasonable to avoid it, and I agree with him. As you start to tweak code, and move things around, or add logic, the increment might go away, move, become redundant etc. and it is often better to perform the increment on a line by itself, or in a loop header instead.
The interesting thing about the ++ operator, besides that it Was a genius idea, is that the prefix and postfix alternatives encode more than just "i = i + 1", they encode an additional evaluation of the left or right hand side of the assignment, so to speak. (Or you could think of it as pre/post evaluation).
So ++i is functionally:
i = i + 1; return i
and i++ is functionally:
temp = i; i = i + 1; return temp
This difference causes additional "trouble" by hiding bugs, and you can see why, if the compiler doesn't optimize the generated code, they have different performance ramifications.
It seems to largely be a matter of personal style and the requirements of the situation.
It's more concise to write i++ compared to i+=1 or i=i+1, and it can help you to remove lines of code that don't communicate an essential fact of the algorithm.
Of course, Jon Skeet is right (as usual) that it can make your code more difficult to understand: mentally distinguishing between ++i and i++ is another cycle your brain has to go through to understand what's going on.
There are situations where more granularity in your code is what you want; there are times when you don't care as much. There aren't really any hard-and-fast rules.
Of course, having said that, I would personally recommend not using i++ or ++i as function arguments (i.e. foo(i++)), since that can introduce some very hard-to-track bugs if you're not very careful, or mixing them with other operators (i.e. Bryan Chen's example of i++ + k++).
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a project where I will create a truth table, and the user will input propositions and its operator and my program will output the truth values providing with a truth table.
I have following questions:
can I use parsing techniques using turbo c?
how should I parse this expression in turbo c? Ex. (p ^ q) -> r
Once I have the expression parsed, how should I go about generating the truth table? Each section of the expression needs to be divided up into its smallest components and re-built from the left side of the table to the right. How would I evaluate something like that?
Can anyone provide me with tips (or links) concerning the parsing of these arbitrary expressions and eventually evaluating the parsed expression?
Let me try to answer your questions.
Yes. There is no reason why you can't.
You need to write some sort of lexer to turn the expression into tokens. Then you can use the shunting yard algorithm to turn the expression into something you can easily evaluate.
Use the result from (2) and evaluate it in a little stack machine. Set each free variable to all possible combinations to generate a truth table.
Parsing arbitrary languages is not possible in general. A good introduction into compiler construction (which is the subfield you are interested in) is found in the Dragon Book (Compilers: Principles, Techniques, and Tools). It's a large field though, I recommed you to take a compiler construction class.
Also, consider ditching Turbo C for something recent. Turbo C is ancient and full of weird quirks.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
In C, for the if statement, sometime we can see that the test 'value is placed before the variable to test, this probably brings some optimization (GCC compiler), but which one ? (but this decreases the readability I think).
Example:
if ( 10 == val) {}
Thanks,
It doesn't have to do with optimization, it's a trick used to avoid accidental assignment and it's called Yoda Convention or Yoda Conditions. It prevents accidental assignment because
if (value = 10)
would compile and would assign 10 to value which is not what you want if you meant if (value == 10) (although some compilers can warn about this and suggest extra parentheses to avoid the ambiguity), this
if (10 = value)
would not.
Since compilers can warn, and when you have experience this is a very uncommon mistake I would advice against this. Because it's difficult to read it and it doesn't feel natural. So be careful and use normal conditions like
if (value == 10)
and to be safe, enable warnings in your compiler to prevent the accidental assignment. See this is equivalent to talking like Yoda, like in this comment and you can see why in the natural language this is uncomfortable, it is too in the code.
The original, historical reason is fear for the ancient, classic bug where you would mix up the = and == operators.
When dinosaurs walked the earth and C was a new language, programmers coming from other languages, most notably Pascal, were particularly prone to write this bug. Because in Pascal, comparison is done by = rather than ==.
To avoid that bug, some of the more confused dinosaurs therefore invented this particular coding style. Because if(10 = val) will not compile. This trick was informally known as the "Yoda conditions", after a Star Wars character who uses backwards, obfuscated language grammar.
Then around 1989, Borland came up with a smart solution to the problem: instead of having programmers make their programs unreadable, let's make a compiler warning for possibly incorrect assignment inside conditions! This was the end of the "Yoda conditions" and every half-decent compiler released since Turbo C has supported a warning for such accidental assignments.
If you encounter someone today, who still thinks this trick is smart, you therefore know that they are either a living dinosaur, or possibly Yoda, the jedi master. In either case you should probably not take any C programming advise from them. But you could ask them why they insist on using a compiler which is worse than Turbo C from 1989.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I am prone to writing code like this:
if (*t) while (*++t);
It reads: if string t does not start with /0, then move to the end.
Note the while loop has no body, so the semicolon terminates it.
I'd like to know if it is good practice to do this? Why and why not?
C is one of the oldest popular language in use today. I believe there's a good chance of finding one or more established style guide(s).
I know that Google has one for their C++ open source projects - http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
Can anyone point me to resources on why or why not write code in certain manner?
Usually it is a good practice to write separate lines of code. Like in case of large pieces of code, debugging is clearer if we write code in separate lines.
It depends! Who is going to have to read and maintain this code? Coding standards exist for two major reasons:
To make code more readable and maintainable. When there are multiple developers, it makes code more consisent (which is more readable).
To discourage common errors. For example, a standard might require putting literals first in conditionals to discourage the assignment-as-comparison bug.
How do these goals apply to your specific code? Are you prone to making mistakes? If this is Linux kernel code, it's a lot more tolerable to have code like this than if it's a web app maintained by entry level programmers.
It reads: if string t does not start with /0, then move to the end.
Then consider putting a comment on it that says that.
Surprisingly - it is usually more expensive to maintain code over time than to write it in the first place. Maintenance costs are minimized if code is more readable.
There are three audiences for your code. You should think of how valuable their time is while you are formatting:
Fellow coders, including your co-workers and code-reviewers. You
want these people to have a high reputation of you. You should write code that is easily understandable for them.
Your future self. Convoluted code may be obvious while you are
writing it, but pick it up again in two weeks, and you will not
remember what it means. The 'concise' statement that you wrote in 10
minutes will someday take you 20 minutes to decipher.
The Optimizing Compiler, which will produce efficient code no matter
whether your line is concise or not. The compiler does not care - try to save time for the other two. (Cue angry remarks about this item. I am in favor of writing efficient code, but concise styles like the one we are describing here will not affect compiler efficiency.)
Bad practice, because not easy to parse. I'd do
while (*t) ++t;
and let the compiler do the tiny bit of optimization.
The textual translation of it reads even shorter than yours
advance t until it points to a 0
Although you can write some pretty clever code in one line in C, it's usually not good practice in terms of readability and ease of maintenance. What's straightforward for you to understand may look completely foreign to someone maintaining your code in future.
You need to strike a balance between conciseness and readability. To this end, it's usually better to separate the code out so each line does one thing.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
If I can do a cycle with for and while both, which should I choose?
[for]
int num = 10;
int i;
for (i=0; i<num; i++)
{
/* ... */
}
[while]
int num = 10;
int i = num;
while ( i-- )
{
/* ... */
}
The choice between for and while is just matter of clarity:
K&R . Chapter 1. The For statment:
The choice between while and for is arbitrary, based on which seems
clearer. The for is usually appropriate for loops in which the initialization and
increment are single statements and logically related, since it is more compact
than while and it keeps the loop control statements together in one place.
Performance, of course, depends on the implementation in the language used. However, in most cases and with most compilers, the generated code from both loops will pretty much be the same.
A rule of thumb would be to use while when you don't know exactly how many times you want to iterate. In your example, it doesn't make much difference. Use what's clearer to you.
And yes, declarations in the for loop are only allowed in newer versions of C (C99).
Usually, you'd use a for loop for something like that because you know before you start the loop how many times you need the loop to run. while loops are more for when you don't know how many times you're going to have to repeat, and something that the user inputs or some random int will change it
In the example above, you should use a for loop since it clearly expresses the intent of what you intend. "Do this loop num times". Also, it is much simpler for the compiler to potentially optimize for loops into vector assembly operations.
You should use a while loop when you have a clearly expressible condition like
"Read lines until EOF" or some other condition that doesn't have an easily enumerable solution.
Also, I consider it poor practice to depend on the fact that 0 is false. You should clearly write the condition that exits the loop.
Every program solve in while loop that can be solved in for loop,but for loop suitable for:-
1--> If i know how many time the loop Will execute and while loop is suitable for if i don't know how many time the loop will be executed.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I want to obfuscate code just for fun. I'm looking at code from the international obfuscated c contest: http://www.ioccc.org/ And I seriously just have no idea how to even start reverse engineering some of this code to make anything of sense.
What are some common obfuscation techniques and how do you make sense of obfuscated code?
There is a lot of different techniques to obfuscate code, here is a small, very incomplete list:
Identifier mangling. Either you will find people using names like a, b, c exclusively, or you find identifiers that have absolutely nothing to do with the actual purpose of the variable/function. Deobfuscation would be to assign sensible names.
Heavy use of the conditional evaluation operator ? :, replacing all occurences of if() else. In most cases that's a lot harder to read, deobfuscation would reinsert if().
Heavy use of the comma operator instead of ;. In combination with 2. and 4., this basically allows the entire program to be one single statement in main().
Recursive calls of main(). You can fold any function into main by having an argument that main can use to decide what to do. Combine this with replacing loops by recursion, and you end up with the entire program being the main function.
You can go the exact opposite direction to 3. and 4., and hack everything into pieces by creating an insane amount of functions that all do virtually nothing.
You can obfuscate the storage of an array by storing the values on the stack. Should you need to walk the data twice, there's always the fork() call handy to make a convenient copy of your stack.
As I said, this is a very incomplete list, but generally, obfuscation is usually the heavy, systematic abuse of any valid programming technique. If the IOCCC were allowing C++ entries, I would bet on a lot of template code entering, making heavy use of throwing exceptions as an if replacement, hiding structure behind polymorphism, etc.