One line assignment according condition in c/c++ - c

Hi,
i would like to know which one of these assignments is faster, safer, better etc. and possibly why:
int choice = fgetc(stdin);
unsigned int bSize;
choice = fgetc(stdin)
1:
bSize = (choice == 'y' || choice == 'Y') ? 256 : 128;
2:
bSize = 128 + ((choice == 'y' || choice == 'Y') << 7);
Thanks.

Regarding speed, this would be at least as fast as choice 2:
bSize = 128 << (choice == 'y' || choice == 'Y');
Whether that would be faster than choice 1 is not immediately obvious to me. However, for tuned performance on an unknown platform, I think that I like the suggested variant on choice 2. The reason is that, at the hardware level, choice 2 (original or variant) does not involve reloading the program counter, but invokes a relatively straightforward shift-register operation, involving relatively few transistors. (Actually, if you want to get really technical about it, I am given to understand that the shift is probably accomplished by multiplexing. To detail that would be too much for the present format, but the point is that the output of (choice == 'y' || choice == 'Y') is effectively piped straight to one of the multiplexer's control lines. Anyway, it's really fast.)
Regarding whether one can safely use the evaluated condition in the manner suggested, ISO/IEC 9899:1999 (E), sect. 6.5.14.3, guarantees that one can safely do this. It reads, "The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int."
(#PaulR rightly observes that electronic-theoretical considerations like the ones this answer offers are not decisive. One must profile actual code on an actual platform to tell for sure which is faster. Nor is this a mere quibble on #PaulR's part. It is all well to argue that choice 2 would be faster, but this does not mean that is is faster. Depending on the CPU in use, branch-predicting or other hardware could promote choice 1, nor would I be extremely surprised if it did.)

In my opinion 'Choice 1' is 'faster' because there's only one assignment operation done after the comparison. In 'Choice 2' it does '+' and '<<' along with the comparison part. 'Choice 1' is 'safer' because it is more readable than the other choice so programmer will have less chance to do error in writing it. Choice 1 is 'better' because of the previous two reasons.

Related

Some confusion with regards to parenthesis in C

Please bear with me, I am trying to learn C as my first programming language and am only 15 minutes in.
Why must parenthesis be used here:
while ((number1 = number2))
...when they do not need to be used here?
while (number1 <= number2)
Thanks in advance.
In:
while (number1 = number2)
number2 is being assigned to number1.
This is optically very similar to comparing number1 and number2, i.e.:
while (number1 == number2)
So a warning is produced in the former case. In order to suppress that warning you need to place the parentheses around the assignment, i.e.:
while ((number1 = number2))
It is a very common mistake to write
if ( a = b ) // assign b to a, branch if result is non-zero
when you meant to write
if ( a == b ) // *compare* b to a, branch if equal
leading to all kinds of mayhem.
It's such a common mistake that most compilers will issue a warning if they see an assignment in a conditional like that. To tell the compiler, "no, I really know what I'm doing", you surround the assignment in an additional set of parentheses:
if ( ( a = b ) )
This basically means, "yes, I intend to assign b to a and branch on the result, shut up."
If I could time travel back to Bell Labs in 1970, this is one of several decisions I'd slap Ritchie over. An entire class of bugs would never have existed if the assignment operator had been := or something equally dissimilar to comparison.
Who said there is a must? You can omit it too.
while (number1 = number2)
yes this would generate compiler warning because you are assigning and checking the assigned value without parentheses. But this is legal and bad practice.
So the reason they did this is to avoid the warning about which the compiler complained. (You shouldn't skip warning to follow a bad practice - rather allow compiler warnings and try to solve them diligently).
Though as you are beginner - aware of the statement, here the while statement is basically
while(number2)
Point: The most common to use would be to while(number1 == number2).
Also does the same thing as the previous one. Who said in the second one you can't? You can.
while ((number1 <= number2))
This is a matter of opinion. Many programmers will still wrap a comparison in parentheses for clarity. That's to make them more legible. For instance:
while(i == 0) //comparison
while(i = 0) //assignment (and therefore, infinite loop)
but more commonly, because chains of conditions can become very hard to read, and getting into the habit of parenthesizing your comparisons makes complex comparisons easier to understand:
//whiskey tango foxtrot
while(i == 0 || j == i && k == 5 || f == "pancakes")
//oh, now it's clear that we're not checking "i && k". Easier to read!
while((i == 0) || (j == i) && (k == 5) || (f == "pancakes"))
//now I've guaranteed i and j both have the value "0" by using parentheses,
//or we get false; but everything is still clearly separated.
while(((i == 0) || (j == i)) && (k == 5) || (f == "pancakes"))
First off, the first example is extremely bad practice. It's not comparing number1 and number2, it's setting the value of number1 to the value of number2. See https://freedom-to-tinker.com/2013/10/09/the-linux-backdoor-attempt-of-2003/ for some more information.
That said, both forms are allowed; you can always add extra parenthesis. In the case you have above, there is no difference.
That said, odds are good that you're simplifying from an example where multiple conditions are chained together, like
while ((number1 == number2) || (number3 == number4))
As you can see, it makes it a bit easier to see what the code is doing. Technically it's not really necessary here, either (though it's generally considered to be good practice), but it can be necessary for more complicated expressions because different expectations about operator precedence can result in your code doing things you might not expect. To take an example from that page, for something like
e = a < d ? a++ : a = d;
It can take a few moments even for an expect to figure out what is going on, and someone less familiar with C will probably need much longer. On the other hand, if you add parenthesis:
e = ( ((a < d) ? (a++) : a) = d );
Things become much easier to read.

how to use multiple input values to call same function?

First I have to say that i'm completely new to programming and this is my first program. I've watched a 5 hour tutorial before I started this and now I've run into my first problem I can't solve myself. So I hope someone here can help me!
I've written the following code
void printMainMenu();
void printTourMenu();
void assignment1();
void assignment2();
void assignment3();
void assignment4();
void assignment5();
void assignment6();
int main()
{
int userInput;
printMainMenu();
printf("\n\n");
scanf("%d", &userInput);
if(userInput == 4||6)
{
printTourMenu();
}
if (userInput == 1)
{
assignment1();
}
if(userInput == 2)
{
assignment2();
}
if(userInput ==3)
{
assignment3();
}
if(userInput ==5)
{
assignment5();
}
return 0;
all the functions are just pure printf so I just want the user to be able to print 6 different things depending on what they click on, but instead of making two if-statements to do the very same thing depending on the input, I just try and make an if-statement that works with multiple inputs.
the problem is in the if(userInput == 4||6) which i've tried with both
4, 6 and 4||6 where it keeps printing the printTourMenu no matter what I input and then the function i'm actually calling. With 4&&6 it prints printTourMenu only when I input 4 but not when I input 6
so what am I doing wrong? I hope someone will help this beginning programmer :D
Actually, the answer was simple and provided ASAP by Steve Summit:
if (userInput == 4||6)
doesn't do the expected. The correct would be:
if (userInput == 4 || userInput == 6)
IMHO, you should now ask:
So, if if (userInput == 4||6) is wrong – why didn't the compiler complain? (I assume it didn't although I didn't try.)
There are two reasons for this and IMHO you should know these reasons (as you did not yet learn them from your C book).
There are no special boolean types in C. Instead, every integer ≠ 0 is counted as TRUE but 0 is counted as FALSE. Hence, logic operators compute integers, comparison operators as well.
Thus, userInput == 4 || 6 is just a valid arithmetic expression and it has a precise result.
To understand how userInput == 4 || 6 is evaluated you need to know about C operator associativity and precedence also. Both terms can be found by google very easy (because they probably are searched quite often (at least periodically by me)).
I recommend the reference table of cppreference.com: C Operator Precedence.
Studying this table, we see:
operators == and || are both evaluated from left to right.
operator == has lower precedence as operator ||, i.e. == binds stronger, i.e. == is computed first.
Hence, it's starting with two cases:
userInput contains value 4: ⇒ userInput == 4: 1
userInput contains anything else: ⇒ userInput == 4: 0
These first results are applied to the second operator || 6:
1 || 6: 1 (Remember, logic-or operator just checks whether at least one argument is not 0.)
0 || 6: 1
It shows that anything || 6 results in 1.
That's why it was printing the tour menu regardless what you input.
Don't forget: as well as in school math, it is allowed to use parentheses () to override associativity and precedence. So, if you are in doubt just put parentheses around. Normally, they don't have any impact on run-time performance (at least, not as long as you don't change the order of operator evaluation due to this).

Efficiency of using "AND" or "OR"

Which is better to use && or ||? For example if I need to check if input is between 5 and 27 and divisible by 3, is it better to check as
if((num < 5) || (num > 27) || (num%3 != 0))
{
//skip
}
else
{
//operations
}
OR
if((num >= 5) && (num <= 27) && (num%3 == 0)
{
//operations
}
Unless you are doing this in an extremely tight loop, you will never notice any difference whatsoever.
Most C compilers will rewrite the expression to take advantage of short-circuit evaluation anyhow, so for those compilers the order is irrelevant (for C++ there are exceptions).
If your compiler cannot optimize the Boolean math (very unlikely in a modern compiler), the second form is better because it allows for some terms to be skipped.
From the CPU's perspective, || and && will more likely than not take exactly the same amount of time to complete. From the compiler's perspective, transforming between the two will be a trivial operation -- this is certainly a choice it will make correctly for you. Use whichever is clearest to you.
It is far more important for you to make good use of C's short circuiting to ensure that the branch is determined in as few executed instructions as possible.

Short-circuiting and readability

In this line
if ((last_search == NULL) || (last_search != NULL && total_results != 0))
I know that C's short-circuit evaluation rules say that only if last_search is not null will it try and evaluate the right-hand side of ||, hence it's equivalent to writing
if ((last_search == NULL) || (total_results != 0))
and I was advised to use the later by someone, but still isn't the former more readable? Also won't the compiler optimize out the redundant last_search != NULL?
This is subjective, but no, the first variant is not more readable because there's more to read. The most readable code (and the least buggy!) is that which does not exist. Just think what would happen if you wanted to check 3 or 4 conditions at once.
And here's another counterexample: would you write code like this?
if (number < 0) {
}
else if(number >= 0) {
// why not just "else"?
}
As for performance: the compiler would probably optimize the redundant call away, but undoing the performance degradation does not help with the readability degradation.
No it's not. The second one is a lot more readable. Why would you keep the redundant check in there, regardless of whether the compiler will optimize it away?
The first version tells you that last_search is not NULL because it got there, but if you can't tell that from the first condition (last_search == NULL failed), you've probably got bigger issues than readability.
It is not only the short circuit evaluation that makes it unreadable but also the fact of using superfluous comparisons.
if ( !last_search || total_results)
is much easier to read than anything that you proposed.

What is the meaning of '==' in C?

What is the meaning of == and how does it differ from =?
How do I know which one to use?
== is a test for equality. = is an assignment.
Any good C book should cover this (fairly early on in the book I would imagine).
For example:
int i = 3; // sets i to 3.
if (i == 3) printf("i is 3\n"); // prints it.
Just watch out for the heinous:
if (i = 4) { }
which is valid C and frequently catches people out. This actually assigns 4 to the variable i and uses that as the truth value in the if statement. This leads a lot of people to use the uglier but safer:
if (4 == i) {}
which, if you accidentally use = instead of ==, is a compile-time error rather than something that will bite you on the backside while your program is running :-)
The logical-or operator is two vertical bar characters, one after the other, not a single character. Here it is lined up with a logical-and, and a variable called b4:
||
&&
b4
No magic there.
a == b is a test if a and b are equal.
a = b is called an assignment, which means to set the variable a to having the same value as b.
(You type | with Shift-\ in the US keyboard layout.)
== tests equality
= assigns a value
neither are related to ||
I might add that in Finnish and Swedish keyboards. Pipe symbol; |; of OR is AltGr (the right alt) and < key. IF you are using Mac on the other hand it is Alt-7 key.
Gave me a lot of sweat when I first started typing on these keyboards.
Now that you know the difference between '==' and '=", let me put you some words of caution. Although '==' is used as a standard test of equality between comparable variables and '=' used as an internally type-casted assignment, the following programming error is quiet common.
In the below example and similar codes, '=' is know as "Always true" conditional operator.
#include<stdio.h>
int main()
{
int i = 10, j = 20;
if ( i = j )
printf("Equal\n");
else
printf("NOT Equal\n");
return 0;
}
So, the word of caution is "Never use '=' in if statements, unless you have something evil in your mind."

Resources