Operators Flashcards
What is operator precedence?
The order in which operators are evaluated in a compound expression.
When two operators of the same precedence level are next to each other, what determines the order in which they are evaluated (L to R or R to L)?
Associativity rules.
What is a prefix vs. postfix increment/decrement operator
prefix: ++x, –x
postfix: x++, x–
Describe the difference between how the prefix and postfix increment operators work?
The prefix increment/decrement operators are very straightforward. The value of x is incremented or decremented, and then x is evaluated.
The postfix increment/decrement operators are a little more tricky. The compiler makes a temporary copy of x, increments x, and then evaluates the temporary copy of x.
What is a side effect?
a result of an operator, expression, statement, or function that persists even after the operator, expression, statement, or function has finished being evaluated; a permanent change of a value.
T/F: it doesn’t really matter if you use an operator with side effects inside of compound expressions.
F; it’s a good idea to avoid this b/c C++ b/c parameters to functions (for example) are evaluated in a random order, which means you can get different results depending on how the variables are used:
int x = 5;
int nValue = Add(x, ++x);
May evaluate to either 11 or 12.
T/F: any operator which causes side effects should be placed in its own statement?
T; this can wreak havoc otherwise.
How does the comma operator evaluate multiple expressions; what does ‘z’ evaluate to in the following snippet:
int x = 0;
int y = 2;
int z = (++x, ++y);
It uses the rightmost operand; z will be assigned the value of 3 b/c ‘++y’ is being evaluated.
T/F: The comma operator works great with for loops.
T; it allows you to define and manipulate multiple variables with each iteration:
for (int iii = 1, jjj = 10; iii <= 10; iii++, jjj–){}
What is the syntax for the conditional (ternary) operator?
x = (condition) ? some value : some other value;
What is the safest way to test for equality with floating point values?
Use epsilon:
bool IsEqual(double dX, double dY) { const double dEpsilon = 0.000001; // or some other small number return fabs(dX - dY) module that returns the absolute value of a number)
What’s wrong with the following snippet:
int x = 5;
int y = 7;
if (! x == y)
cout «_space;“x does not equal y”;
else
cout «_space;“x equals y”;
the if statement is saying (!x) == y, which is false (!x will evaluate to 0), so the statement will say that they are equal. The correct way to write the if statement if:
if(!(x == y))
T/F: if is best practice to put operands and other operators in parentheses when using ‘!’
T; ‘!’ i intended to operate on the result of other operators. The exception to this rule is if you are negating a single value: (!bValue), as ‘!’ has only one operand to work on so no conflicts will emerge.
What is short-circuit evaluation?
It is used by logical AND (‘&&’) to automatically evaluate an entire statement to false without evaluating the other operands if the first statement if false; this always means the statement will evaluate to false regardless of the other operands.
What is the best practice when mixing && and ||?
Enclose everything in parentheses; && has a higher precedence than ||, so leaving out parentheses can cause incorrect evaluations.
What is De Morgan’s law?
It tells us when we distribute ‘!’ operators we also need to flip the corresponding && or ||
!(x && y) is equivalent to !x || !y
!(x || y) is equivalent to !x && !y
Is !(x && y) the same as !x && ! y
No
What is the conventional way to group bits in binary numbers?
Groups of 4 bits:
1010 0010 1101 0101
What is an algorithm for converting decimal to binary?
x = the multiple of 2 where x is < our decimal number and 2 * x is > than our decimal number.
While x >= 1 if decimal number >= x push a 1 to output decimal number = decimal number - x else push a 0 to output end
x = x/2
end
What is an algorithm for converting binary to decimal?
arry = array of digits in num x = 0 output = 0 arry.each do output = output + ((2**x) * arry[x]) \++x end
How are signed numbers stored in memory?
In two’s complement: The leftmost (most significant) bit represents the sign; 0 for positive and 1 for negative
How can bits be shifted to convert from positive to negative?
negate every bit, then add 1 to the result.
Why do we add 1 when converting from negative to positive?
Consider the following case:
Consider the number 0. If a negative value was simply represented as the inverse of the positive number, 0 would have two representations: 0000 0000 (positive zero) and 1111 1111 (negative zero). By adding 1, 1111 1111 intentionally overflows and becomes 0000 0000. This prevents 0 from having two representations, and simplifies some of the internal logic needed to deal with negative numbers.
What happens to bits pushed off the end of a number when bitshifted to the left or right?
They are lost:
0011 «_space;3 = 1000
What does bitshifting to the left («) effectively accomplish?
Multiplies the number by (2**length of shift) UNLESS bits are lost by being pushed off the end? Right shift effectively divides instead of multiplies UNLESS, again, bits are lost off the end.
What does bitwise NOT (~) do?
It flips every bit, effectively evaluating to ((2**num bits) - original number + 1)
What does bitwise OR (|) do?
Compares bits in each number lined up in columns, returns a 1 if at least 1 bit is a 1, otherwise 0
What does bitwise AND (&) do?
compares bits, only evaluates to 1 if ALL bits are 1, otherwise 0
What does bitwise XOR (^) do?
compares bits, evaluates to 1 ONLY if there are an ODD number of 1's being added, otherwise 0: 0001 // 1 001 1 // 3 01 1 1 // 7 -------- 0 1 0 1 // 5
Why were bitwise operators popular in the early days but not so much today?
Back when memory was scarce, a boolean taking up a byte wasted the other 7 bits; bitwise operators solved that problem by compacting 8 booleans into a single byte. This works because the byte’s value as an integer tells us EXACTLY what the location of boolean in the byte and its value, and knowing this they can be manipulated. Nowadays memory is abundant, so these kinds of optimizations are negligible, except when extreme optimization is required (e.g. scientific programs, games, etc.)
How does ASCII use XOR?
The uppercase value of the letter minus the lowercase letter = 32, and XORing by 32 allows us to convert from one case to the other