How the assignment statement in an if statement serves as a condition? - c

if ((vnd = (struct diam_vnd_t *)g_hash_table_lookup(vendors,vend))) {...}
Can you tell me why it is an assignment but not a boolean expression in the brackets ? And in what situation this assignment can be considered "true" or "false" ?

Quoting C11, chapter §6.5.16, Assignment operators (emphasis mine)
An assignment operator stores a value in the object designated by the left operand. An
assignment expression has the value of the left operand after the assignment,111) but is not
an lvalue.
So, first the assignment will happen, and then, the value that has been assigned will be used as the conditional statement in if.
So, in case of
if (p = 0 )
will evaluate to FALSE and
if (p = 5)
will be TRUE.

The logical operator for "is equal to" is ==
When you're saying vnd = (struct... you are assigning everything after = to the variable vnd. If you want a true or false you need to use ==

C considers anything non-zero to be true, and anything 0 to be false.
This assignment's value is equal to the value it assigns to vnd, in this case, a struct diam_vnd_t *. The if statement checks whether or not vnd is NULL after the assignment.
This would be equivalent to:
vnd = (struct diam_vnd_t *)g_hash_table_lookup(vendors,vend);
if (vnd) {...}

Assignment is always done with one equal sign. =
int i;
i = 0; //assignment
This assigns 0 to an integer called i.
The same thing happens with your if statement. Whether or not it is in an if statement is irrelevant.
(vnd = (struct diam_vnd_t *)g_hash_table_lookup(vendors,vend))
To do a boolean expression, you need to use ==.
(vnd == (struct diam_vnd_t *)g_hash_table_lookup(vendors,vend))
This will return true or false based on the comparison of the 2 items

Related

condition check in If statement [duplicate]

I'm studying C from A Book on C by Kelley-Pohl, and there's this exercise that I don't understand:
int a = 0, b = 0, x;
x = 0 && (a = b = 777);
printf("%d %d %d\n", a, b, x);
x = 777 || (a = ++b);
printf("%d %d %d\n", a, b, x);
They just say to imagine the output and compare it to the real one. I thought the output would have been
777 777 0
778 778 1
but it is
0 0 0
0 0 1
From the C Standard (6.5.13 Logical AND operator)
3 The && operator shall yield 1 if both of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
4 Unlike the bitwise binary & 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 equal to 0, the second
operand is not evaluated.
In this expression statement
x = 0 && (a = b = 777);
the first operand compares equal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed. So the variable x will be set to 0 according to the paragraph #3 of the section.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
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.
In this expression statement
x = 777 || (a = ++b);
the first operand compares unequal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed.. So the variable x will be set to 1 according to the paragraph #3 of the section.
If you will change the order of the operands in the expressions like
x = (a = b = 777) && 0;
x = (a = ++b) || 777;
you get the expected by you result.
The && operator uses lazy evaluation. If either side of the && operator is false, then the whole expression is false.
C checks the truth value of the left hand side of the operator, which in your case is 0. Since 0 is false in c, then the right hand side expression of the operation, (a = b = 777), is never evaluated.
The second case is similar, except that || returns true if the left hand side expression returns true. Also remember that in c, anything that is not 0 is considered true.
Hope this helps.
Another trap in this expression is that; the precendence of the operators. Such as &&, || (logical and, logical or) operators have higher precedence to the assignment operator(=).
in this case x=(0&&(a=b=777)) is same as x=0&&(a=b=777), however x=(0&(a=b=777)) is more readable than the previous one.
Logical operators select one of their operands and returns the result accordingly.
They also force their operands to be boolean as true or false.
In this expression "x=0&&(a=b=777)" since the first operand is false the result will be equal to first operand.Second operand is short circuited and will not be executed.So the output will be a=b=0, x=0.
x=777 || (a=++b) in this expression since the first operand is true the result will be equal to the first operand and logical operator will not check the second operand, logical OR operator will bypass the second operand.In this expression since the first operand is true (777 is converted to true) the result will be True means x=1.Since the second operand is skipped "a" and "b" values will remain same as their previous values, in this case 0,0

Chaining assignment in an if condition

Hi just wondering if you use a chained assigment in an if condition, would the leftmost variable be used to check the if condition
like a=b=c , its a thats ultimetly checked and not b or c
#include <stdio.h>
int main()
{
int a, b, c =0;
// does this reduce to a == 100 and the variables b or c are not checked if they are == to 100 but simply assigned the value of 100 ?
if( (a = b = c = 100) == 100)
printf( "a is 100 \n");
return 0;
}
The expression is not actually checking a or b or c.
An assignment expression, like any expression, has a value. And in this case it is the value that is stored. However, the actual storing of the value in an object is a side effect so there's no guarantee that it has happened at the time the comparison operator is evaluated.
So the condition is actually more like:
if (100 == 100)
With the assignment to a, b, and c happening in a manner that is unsequenced with respect to the comparison.
This is spelled out in section 6.5.16p3 of the C standard regarding assignment operators:
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
The condition is always true. Your code is equivalent to:
a = 100;
b = 100;
c = 100;
printf( "a is 100 \n");

Explanation of shortcuts in C

Can someone explain what exactly is happening in these two statements listed below:
1) int enabled = val == 0; //val is an int
2) int sync = param || (foo->delay == NULL); //param and delay is both int
int enabled = val == 0;
read as
int enabled = (val == 0);
and
(val == 0)
will be either 0 or non zero if val is 0 or not. enabled will then be initialized with that value
Equivalent to:
int enabled;
if(val == 0)
{
enabled = 1;
}
else
{
enabled = 0;
}
now you do that same analysis on the second one
You will set the variable enabled to 1 if val is equal to 0 and 0 otherwise.
sync will be equal to 1 if param is non-zero and in case it is 0 then it will be 1 if foo->delay is NULL else it will be 0.
From standard §6.5.9p3 backing up what I said:
The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence.108) 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.
Also in case || there is standard saying the evaluation logic: from §6.5.14
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.
Also in the same section the rule which dictates what will be the result if param is non-zero.
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
C only adopted a true boolean type from C++ with C99, though it named it _Bool so it wouldn't conflict with pre-existing code and provided the header <stdbool.h> to make it nicer.
The prior convention that only 0 is considered falsey (a literal zero, which in a pointer-context is a null-pointer), and anything else truthy was not changed. (That's the reverse to how command shells do it by the way.)
All boolean operators and conversion from _Bool use canonical values of 0 and 1.
That should be enough history and details to understand the code.

Explanation for this function's output

I am doing review questions which ask me "What is the output of the following," and I am having some trouble understanding something about this function:
int a = 1, b = 1, c = -1;
c = --a && b++;
printf("%d %d %d", a, b, c);
The output is 010. My question is about line 2, c = --a && b++. How is this line processed, and how does it work/change the values? And if it were c = --a || b++? From my understanding I thought the output would be 020.
The key concept to understanding the result is short-circuit evaluation of Boolean operators (&& and ||) -- if, after evaluating the left-hand side of a Boolean operator, the value of the right-hand side cannot affect the overall result, then it will not be evaluated and any side-effects it would produce will not happen.
In the first case, since --a evaluates to 0 (=false) the second part of ... && ... is not evaluated, since "false AND anything" will always be false. Specifically, b++ is never executed, and so its value remains 1 in the output.
In the case of --a || b++, the value of the whole expression cannot be determined by the left-hand side ("false OR something" can still be true) so the b++ is evaluated (and it's side-effect, incrementing b, happens).
The other concept needed to fully understand the results is the difference between pre- and post-increment/decrement operators. If the -- or ++ appears before the variable (as in --a) then the variable is decremented or incremented first and new value is used to evaluate the whole expression. If the -- or ++ appears after the variable (as in b++) then the current value of the variable is used to evaluate the expression and the increment/decrement happens after this has happened.
It should be noted that expressions that try to combine two or more instances of --/++ of the same variable (e.g. a++ + ++a) are quite likely to invoke undefined behaviour -- the result may vary by platform, compiler, compiler and even the time of day.
In the expression c = --a && b++, a gets decreased and returned. Now the second argument of the expression --a && b++ is not evaluated because of short circuit evaluation---once we see that --a==0 we already know that the expression will be 0 regardless of what is the other argument---, so b remains unchanged.
Decreased a is 0 and b remains 1.
The output is, as you suggest, 0 1 0.
Regarding the second question, if you write c = --a || b++, the variable a again goes to zero but the expression can still evaluate to true---we must thus evaluate the second part as well, thus executing b++ which returns 1 and increases b. In this case the output would be 0 2 1, because c is assigned the value of 0 || 1 which is 1.
In short, read up on
pre- and post-increment in C and C++ and on
short circuit evaluation.
The thing you need to focus on here first is the properties of prefix and postfix operators and their differences.
For Postfix increment and decrement operators, C11, chapter §6.5.2.4, (emphasis mine)
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented [...] The postfix -- operator is analogous to the postfix ++ operator, except that the value of
the operand is decremented.
For Prefix increment and decrement operators, C11, chapter §6.5.3.1, (emphasis mine)
The value of the operand of the prefix ++ operator is incremented. The result is the new
value of the operand after incrementation. [...] The prefix -- operator is analogous to the prefix ++ operator, except that the value of the
operand is decremented.
Now, there comes the property of the Logical AND (&&) operator. From chapter §6.5.13, (again, emphasis mine)
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 equal to 0, the second
operand is not evaluated. [...]
So, in your case,
int a = 1, b = 1, c = -1;
c = --a && b++;
gets evaluated as
c = 0 && .....; // done..., a is decremented to 0,
// so, LHS of && is 0, RHS is not evaluated,
// b remains 1
// and finally, C gets 0.
On the other hand, if logical OR (||) would have been used, then, as per the property, mentioned in chapter §6.5.14
[...] 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.
So, for the case
int a = 1, b = 1, c = -1;
c = --a || b++;
it will be evaluated as
c = 0 || 1; //yes, b's value will be used, and then incremented.
So,
printf("%d %d %d", a, b, c);
will be
0 2 1
b++ is simply never executed because --a evaluates to false in an and condition.
The right side of the and is never executed because not needed. Hence b is never incremented and hence the output you did not expect.
c = --a && b++;
In this first --a is evaulated and a becomes 0 , as soon as 1 operand of && is false , b++ is not evaluated , therefore ,b remains 1 and c becomes 0.
The line :
c = --a && b++;
decreases a to 0, so the statement 0 && anything else results to 0. This is why a and c result to 0, as it seems you have understood.
Now let's see the part you don't get. When a is evaluated to 0, the right part of && does not need to be evaluated, as no matter what the value of the right part will be calculated to be, the result will be 0. This means that b++ will not be evaluated and therefore b will retain its initial value. This is why you see the value 1 instead of 2, and consequently the output 0 1 0 instead of 0 2 0.
--a : mean you decrease a before do the line. b++: increase b after do the line. so that c ( at that time ) = 0+1 =1; then: a =0, b = 2, c =1; OK

What does " = " instead of " == " mean in c if statement?

#include <stdio.h>
int main(){
int b = 10,a;
if (a = 5){
printf("%d",b);
}
}
In the above program if statement always returns true even if i change the data type of the variable "a" from "int" to "char".
What does = mean in the if statement??
= is an assignment operator in C. According to C99 6.5.16:
An assignment operator stores a value in the object designated by the
left operand. An assignment expression has the value of the left
operand after the assignment, but is not an lvalue.
It means that expression a = 5 will return 5 and therefore instructions inside if block will be executed. In contrary, if you replaced it with a = 0 then 0 would be returned by assignment expression and instructions inside if would not be executed.
A single = means an assignment operator, that means you are changing the value of a and using this value in the if statement.
if(a = 5) {
// some code
}
is the same of:
a = 5;
if(a) {
// some code
}
The == means a operation of logical equivalence, witch will return 1 if the two values are the same or 0 if they aren't the same.
Assignment operator returns the assigned value back.
"if" statement decides to true if checked value is other than zero
So:
"if (a=0)" returns false
"if (a=x) where x!= 0" returns true
Thus you should use "==" operator in the if statement as other friends told.
The single = will assign the value 5 to a. Assignment will evaluate true if the assignment value evaluates true (i.e. not 0, null etc). If it evaluates true, the function will branch into the if statement block. And there's the side effect that a gets value 5.
Please note that in C it is allowed in a boolean expression to use the assignment operator. Because of that = as assignment must be a different symbol than = for comparisson.
Because in a language such as BASIC there can be no confusion of whether the programmer means assignment or comparisson, BASIC uses the same symbol for the two meanings:
C:
if ((a=5)==5) ... // a is set to 5 and then compared to 5
Basic:
a = 5 ' assignment
If (a = 5) Then ' comparison

Resources