a=5; b=0; c=1;
if(b=2) c = a++ & b;
else a=4;
b = a && b;
Code is in C. How will this code work? What will a, b, c have values? What
does b = a && b mean in C?
In C, && is the logical AND operator. Therefore a && b is the result of the logical operation "a AND b". Since C originally had no boolean type you often see int being "abused" as an substitute. An int is "true", if it has a non-zero value - and "false" if it is zero. (I think C99 added some boolean type called _Bool, but I'm not exactly sure on that one.) So the result of the expression a && b is either 1, if both a and b are non-zero, or zero if (at least) one of them is zero. That also is what gets assigned to b in b = a && b; then.
However, there also is the binary & operator in C, which is the bitwise AND and does something different than &&. This can also be a source of confusion and unintended errors/bugs in C code, because accidentally missing a & in && changes the behaviour of the compiled code.
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'm learning C as Javascript developer and a common mistake that I make is when I'm supposed to define multiple variables in C like this
int a, b, c;
a = b = c = 0;
I accidentally do it the Javascript way
a,b,c = 0;
I'm wondering what the above is called and when I should define variables like this.
I'm wondering what the above is called....
Two things about this statement
a,b,c = 0;
First, this is same as
a;
b;
c = 0;
The expression a; and b; result is unused.
The compiler must be throwing warning messages on this statement. When I compiled with clang compiler, I am getting following warnings:
p.c:6:2: warning: expression result unused [-Wunused-value]
a, b, c = 9;
^
p.c:6:5: warning: expression result unused [-Wunused-value]
a, b, c = 9;
^
and Second, the , in the statement is , (comma) operator.
Precisely stated, the meaning of the comma operator in the general expression
e1 , e2
is evaluate the subexpression e1 and discards the result , then evaluate e2; the value of the expression is the value of e2.
So, the value of expression a,b,c = 0 is value of c = 0. The variable a and b will remain uninitialised.
May you can try this and check the variable values after this statement:
a = 99, b = 5, c = 0;
Since you are learning C, let me tell you one more thing - The , (comma) act as separator in function calls and definitions, variable declarations, enum declarations, and similar constructs. To begin with, check this.
and when I should define variables like this.
The statement a,b,c = 0; is not definition of variable a, b and c. You have defined the variable a, b and c here
int a, b, c;
Note that in this statement, the , is act as separator.
Its use is completely depends on you as long as you know very well about it. One of the very common use of , (comma) operator is in for loop, where it can be used to initialise multiple variables and/or increment/decrement loop counter variable and other variables etc., for example :
for (i = 0, j = some_num; i < some_num; ++i, --j) ....
Divide it up by the operators:
int a, b;
a = b = 10;
^ ^^^^^^
| Right operand
Left operand
Here, first it calculates b = 10 to assign to a. b = 10 "returns" the new value of b which is 10, and that is assigned to a. It works similarly with more variables:
int a, b, c;
a = b = c = 10;
^^^^^^-Done first
^^^^^-Done second
^^^^^-Done last
a, b, c = 10 does not work the same way. First of all, you have to declare them first before assigning. Also, this uses the , operator which has a lower precedence than =, so the line is equivalent to a; b; c = 10;. As you can see, nothing really happens to a or b and only c is set to 10.
The comma used as an operator is called the comma operator.
For details, read a C standard, like n1570 (§6.5.17) or later. The semantics is defined as:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value
Of course, inside function calls like printf("x=%d y=%d\n", x, y) the comma is separating arguments. Inside macro invocations and definitions also. In that case, it is the comma punctuator (see n1570 §6.5.2, 6.7, 6.7.2.1, 6.7.2.2,6.7.2.3, 6.7.9)
If you compile with GCC, invoke it as gcc -Wall -Wextra -g. You could get useful warnings.
Consider, if so allowed, to use the Clang static analyzer (or other tools like Frama-C or Bismon; you may contact me in 2021 by email to basile.starynkevitch#cea.fr)
Take inspiration from the source code of existing free software programs like GNU make or GNU bash. They rarely use the comma operator.
In c language you can define the variable using one line
int a,b,c;
This is same as
int a;
int b;
int c;
You can define and initialize this one like this
int a,b,c;
a=b=c=10;
if you write
int a,b,c;
a,b,c=10;
it will initialize c as 10 but others will not inilizes as 10;
a and b will be defined but not initialized it will return garbage 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 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.