I tried running the following code in C:
#include <stdio.h>
int main() {
int a = 10, b = 5, c = 5;
int d;
d = b + c == a;
printf("%d", d);
}
I got the output as d = 1. Can someone please explain to me what happens when we use == like this?
§6.5.9 (== and !=)-http://c0x.coding-guidelines.com/6.5.9.html
The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence.)Each of the operators yields 1 if the specified relation is true and 0 if it is false. The result has type int.
For any pair of operands, exactly one of the relations is true.
So here as b+c is equal to a as both has value 10 therefore it yields 1.
Because b + c is executed first, and after is evaluate comparison with == operator.
In c, addition has higher precedence than ==, so it adds b and c before comparing the result to a, since it is true it results in 1, if it was false it would result in 0.
== is the equal-to operator. It returns 1 if the two sides are equal and 0 otherwise.
Related
This question already has answers here:
if statement integer
(3 answers)
Closed last month.
I have an exam at uni from C and I was looking through the exams from the previous years and I stumbled over this problem:
What is the value of d after executing the following sequence?
int a=36, b=20, c=30, d;
d = c?(a? a: c):(b? c: b);
There was another exercise like this, but in those parenthesis there were other expressions:
d = (a>b) ? ((a>c)? a: c): ((b>c)? b: c);
I put the 2 codes in ChatGPT and it told me that they are called ternary operators.
I understand that in the second example we are comparing a with b, a with c, b with c, then we are giving d a value based on the comparisons. But in the first example, there are no comparisons, only variables. Moreover, the test will be on paper, so I won't be able to run the code on a computer. How do I read the syntax of the first example, what does it mean? Am I still comparing the 3 variables, or is it something different?
I ran the codes on CodeBlocks and on VS for both exercises, with the same values (a = 36, b = 20, c = 30), and they both gave me the same answer:
d = (a>b) ? ((a>c)? a: c): ((b>c)? b: c); //d = 36
and
d = c?(a? a: c):(b? c: b); //d was still 36.
I don't understand how did I get that answer from the second exercise.
This is the conditional operator; it selects its second or third operand based on its first operand, which is a condition. It is a ternary operator; it has three operands. (But so does the function call f(a, b), with operands f, a, and b.) Do not use ChatGPT for authoritative information.
C 2018 6.5.15 4 specifies the conditional operator:
The first operand is evaluated… The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand (whichever is evaluated), converted to the type described below.
Thus, in c?(a? a: c):(b? c: b), c is evaluated, and the conditional operation proceeds:
If c is not zero, (a? a: c) is evaluated. This operation proceeds:
If a is not zero, a is evaluated.
If a is zero, c is evaluated.
If c is zero, (b? c: b) is evaluated.
If b is not zero, c is evaluated.
If b is zero, b is evaluated.
Evaluation of an object identifier (a, b, or c) simply produces its value. Since c is not zero, (a? a: c) is selected. Since a is not zero, a is selected. a is 36.
The first ternary statement:
d = c?(a? a: c):(b? c: b);
is equivalent to this series of if-else:
if (c) { /* c is non-zero */
if (a) /* a is non-zero */
d = a;
else
d = c;
} else {
if (b) /* b is non-zero */
d = c;
else
d = b;
}
The second one:
d = (a>b) ? ((a>c)? a: c): ((b>c)? b: c);
is equivalent to this series of if-else:
if (a > b) {
if (a > c)
d = a;
else
d = c;
} else {
if (b > c)
d = b;
else
d = c;
}
Some notes:
if (a) is equivalent to if (a != 0).
if (!a) is equivalent to if (a == 0.
The if statement considers any non-zero value to be true, and zero to be false. The block is only entered if the conditional expression evaluates to a non-zero value.
I have three variables: a, b, c. Let's say they are integers. I want to find the first non-zero value among them, in that particular order, without looping. The following seems to work, but I am not sure if that is because I am lucky, or because the language guarantees it:
int main(int argc, char *argv[]) {
int a = 0;
int b = 3;
int c = 5;
int test;
if ((test = a) != 0 || (test = b) != 0 || (test = c) != 0) {
printf("First non-zero: %d\n", test);
} else {
printf("All zero!\n");
}
return 0;
}
Is the repeated assignment with short-circuiting shown here guaranteed to work as intended, or am I missing something?
This might be one place where a three-letter answer would be acceptable, but a two-letter answer might require more explanation.
It would!
Because of the nature of the OR operator if any of the condition is
true then the test stops.
Thus i think what you did was basically equivalent to:
test = a != 0 ? a : b != 0 ? b : c != 0 ? c : 0;
printf("%d\n",test);
but heck yours looks good.
[update]
As per what chqrlie mentioned it can be further simplified to:
test = a ? a : b ? b : c;
Yes, your expression is fully defined because there is a sequence point at each || operator and the short circuit evaluation guarantees that the first non zero value assigned to test completes the expression.
Here is a crazy alternative without sequence points that may produce branchless code:
int test = a + !!a * (b + !!b * c);
printf("%d\n", test);
The code is very bad practice but it is guaranteed to work fine.
This is because the || and && operators have special characteristics - unlike most operators in C, they guarantee that the evaluation of the left operand is sequenced (executed) before the evaluation of the right operand. This is the reason that the code works. There's also a guarantee that the right operand will not be evaluated if it is sufficient to evaluate the left one ("short circuit"). Summarized in C17 6.5.14/4:
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
"Sequence point" being the key here, which is what gives the expression a deterministic outcome.
Had you used pretty much any other operator (like for example bitwise |), then the result would be undefined, because you have multiple side effects (assignments) on the same variable test in the same expression.
A more sound version of the same algorithm would involve storing the data in an array and loop through it.
I have a question, how the compiler operate on the following code:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d = (b == c++) ? (c+1) : (c-1);
printf("d = %i\n", d);
}
I am not sure why the result is d = 11.
In int d = (b == c++) ? (c+1) : (c-1);:
The value of c++ is the current value of c, 11. Separately, c is incremented to 12.
b == 11 is false, since b is 12.
Since (b == c++) is false, (c-1) is used. Also, the increment of c to 12 must be completed by this point.
Since c is 12, c-1 is 11.
d is initialized to that value, 11.
According to the C Standard (6.5.15 Conditional operator)
4 The first operand is evaluated; there is a sequence point between
its evaluation and the evaluation of the second or third operand
(whichever is evaluated). The second operand is evaluated only if the
first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second
or third operand (whichever is evaluated), converted to the type
described below.110)
So in the initializing expression of this declaration
int d = (b == c++) ? (c+1) : (c-1);
the variable b is compared with the value of the variable c because the post-increment operator returns the value of its operand before incrementing it.
As the values are not equal each other (b is set to 12 while c is set to 11) then the sub-expression (c-1) is evaluated.
According to the quote there is a sequence point after evaluation of the condition of the operator. It means that after evaluation of the condition c has the value 12 after applying the post-increment operator to the variable c. As a result the variable d is initialized by the value 1 (12 - 1).
Translated to a regular if-statement your code would look like this:
int b=12, c=11;
int d;
if (b == c++)
d = c+1;
else
d = c-1;
The clue here is that c is incremented after the condition is checked. So you enter the else state but c already has the value 12 there.
Beacuse the condition is false, therefore the false case will happen: c-1, but since you incremented c in the condition by c++, therefore c is now 12. The result thus 12 - 1 which is 11.
EDIT:
What OP misunderstood was the post increment.
So what actually happen is like this:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d;
if (b == c) { // 12 == 11 ? -> false
c = c + 1;
d = c + 1;
} else { // this executes since condition is false
c = c + 1; // post increment -> c++ -> c = 12 now
d = c - 1; // 12 - 1 = 11 -> d = 11
}
printf("d = %i\n", d);
}
Refer to Ternary Operator.
Syntax
condition ? value_if_true : value_if_false
So, you wrote
int d = (b == c++) ? (c+1) : (c-1);
In this situation, the result will be 11 because, after if checks, 'c' value is increased(c+1=12) and only after that it sets 'd' value as c(12)-1 which is 11.
If you used, for example:
int d = (b == ++c) ? (c+1) : (c-1);
"c" value would be increased before checking the statement, so it would be true and "d" value would be c(12)+1 which is 13.
I recently took an exam on C programming that provided these expressions:
int a = 3, b = 10, c = 4, d = 6;
(c >= d) || (a > b)
correction: the first expression is: (c <= d) || (a > b)
(a <= b) && (c == d)
and a question asking how many comparisons were made in each expression. I said there were three comparisons in each expression. In the first are great than or equal to, OR, and greater than. In the second is less than or equal to, AND, and equal to. But according to the grader, there's only one comparison in the first expression and two in the second.
Can anyone please explain why?
Are the integers relevant?
The integers are quite relevant to the context because of short-circuiting operators || and &&.
For || the second comparison is never made if the first expression is true.
For && the second comparison is never made if the first expression is false.
Also, the AND and OR operators themselves are not comparisons.
Given the numbers are:
int a = 3, b = 10, c = 4 , d = 6;
For the first expression (after your update):
(c <= d) || (a > b)
variable c is smaller than d (4 is smaller 6), so that whole expression turns out true whatever the value of the second part is, so that's only 1 comparison.
For the second:
(a <= b) && (c == d)
Variable a is smaller than b, but the program has to check that other part too (in case c is not equal to d and they are in fact different), so here there are also 2 comparisons.
The point of this question was to determine whether you understood the concept of short-circuiting for || and && in C. These are logical connectives, not comparisons.
In your example, you are given:
int a = 3, b = 10, c = 4, d = 6;
You are then asked how many comparisons are performed for:
1. (c <= d) || (a > b)
2. (a <= b) && (c == d)
Both of these expressions contain two comparison operations, but that does not mean those comparisons will actually be performed.
In case (1), it first compares c vs. d, using <=. The result of this is true (i.e. 1). This is all it needs to determine that the result of the || operation will be true (i.e. 1), so it skips the second comparison of (a > b), since it's not needed to obtain the final result. This is called short-circuiting.
In case (2), it first compares a vs. b using <=. The result of this is true (i.e. 1), so it proceeds to the second comparison of (c == d). The result of this is false (i.e. 0), so the final result is false (i.e. 0).
So for (1) it only needed to perform one comparison, but for (2) it needed to perform two comparisons. If the values of the variables are changed, then the number of comparisons could change as well.
int a;
scanf("%i", &a);
printf("%i", a&&1);
In this program, no matter the input it spits out a 1, even when I try even numbers. The only exception is when a = 0. I might not be understanding the AND operator correctly, but for any even number shouldn't the output be 0?
Because the && operator returns a non zero value if both its operands are not zero. Maybe you mean &.
int a;
if (scanf("%i", &a) == 1)
printf("%i", a & 1);
&& is the logical AND operator.
& is the bitwise AND operator.
Operator && is the logical AND operator that returns true/false.
In C language false is 0 (zero) otherwise 1 (one) for true as C does not have boolean type.
So the result of your operator is correct and as expected.
If you insist on using bool type you can include definition for it as below
// standard way
#include <stdbool.h>
which is basically
#define bool _Bool
#define true 1
#define false 0