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

#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

Related

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");

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

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

Strange behavior from a simple C program

If I run the following code, graph[0][0] gets 1 while graph[0][1] gets 4.
In other words, the line graph[0][++graph[0][0]] = 4; puts 1 into graph[0][0] and 4 into graph[0][1].
I would really appreciate if anyone can offer reasonable explanation.
I observed this from Visual C++ 2015 as well as an Android C compiler (CppDriod).
static int graph[10][10];
void main(void)
{
graph[0][++graph[0][0]] = 4;
}
Let's break it down:
++graph[0][0]
This pre-increments the value at graph[0][0], which means that now graph[0][0] = 1, and then the value of the expression is 1 (because that is the final value of graph[0][0]).
Then,
graph[0][/*previous expression = 1*/] = 4;
So basically, graph[0][1] = 4;
That's it! Now graph[0][0] = 1 and graph[0][1] = 4.
First let's see what is the unary (prefix) increment operator does.
The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation.
So, in case of
graph[0][++graph[0][0]] = 4;
first, the value of graph[0][0] is incremented by 1, and then the value is used in indexing.
Now, graph being a static global variable, due to implicit initialization, all the members in the array are initialized to 0 by default. So, ++graph[0][0] increments the value of graph[0][0] to 1 and returns the value of 1.
Then, the simpllified version of the instrucion looks like
graph[0][1] = 4;
Thus, you get
graph[0][0] as 1
graph[0][1] as 4.
Also, FWIW, the recommended signature of main() is int main(void).
You are adding one to graph[0][0], by doing ++graph[0][0]. And then setting graph[0][1] to 4. Maybe you want to do graph[0][graph[0][0]+1] = 4
At first your variable graph[10][10] is static so it will be initialized with value 0.
Then line graph[0][++graph[0][0]] = 4 ; here graph[0][0] = 0 in expression you just incrementing the value of graph[0][0] so basically you assigning graph[0][1] = 4; yourself
Note that you have used pre-increment operator (++x) so it first get incremented and value is changed but if you would have use post-increment operator(x++) then graph[0][0] = 4; itself
Let's line up the facts about this expression
graph[0][++graph[0][0]] = 4;
Per 6.5.1, the computation of the array index ++graph[0][0] is sequenced before the computation of array element graph[0][++graph[0][0]], which in turn is sequenced before the computation of the entire assignment operator.
The value of ++graph[0][0] is required to be 1. Note that this does not mean that the whole pre-increment together with its side-effects has to "happen first". It simply means that the result of that pre-increment (which is 1) has to be computed first. The actual modification of graph[0][0] (i.e. changing of graph[0][0] from 0 to 1) might happen much much later. Nobody knows when it will happen exactly (sometime before the end of the statement).
This means that the element being modified by the assignment operator is graph[0][1]. This is where that 4 should go to. Assignment of 4 to graph[0][1] is also a side-effect of = operator, which will happen sometime before the end of the statement.
Note, that in this case we could conclusively establish that ++ modifies graph[0][0], while = modifies graph[0][1]. We have two unsequenced side-effects (which is dangerous), but they act on two different objects (which makes them safe). This is exactly what saves us from undefined behavior in this case.
However, this is dependent on the initial value of graph array. If you try this
graph[0][0] = -1;
graph[0][++graph[0][0]] = 4;
the behavior will immediately become undefined, even though the expression itself looks the same. In this case the side-effect of ++ and the side-effect of = are applied to the same array element graph[0][0]. The side-effects are not sequenced with relation to each other, which means that the behavior is undefined.

Side effect vs value calculation in GCC ternary conditional operator?

I have the following code which produces unexpected results to me:
#include < stdio.h >
int a = 0, value;
int main(void)
{
// Testing the evaluation order of multiple
// conditional operators:
value = (a == 3) ? 3 : (a = 3) ? 5 : 0;
printf("%d\n", value);
return 0;
}
I was expecting for this code to print 3, seeing that the conditional operator evaluates
from right to left and that there is a sequence point at the ? of the first-to-be executed
operation, whereas it actually prints 5.
Is it wrong to assume that side effects of an expression residing between two sequence
points also get calculated when the values of the expressions are?
If i add printf("%d\n" a); i get 3 printed though, so the side effect gets done.
Or is it just that control dosent really pass to the subexpression the value of which
is being calculated "first" officially?
I would rather bet on the latter because changing the value of 'a' to 3 and the rvalue
in the assignment of the second conditional to 4 resulted in short-circuit evaluation
of the first conditional expression, meaning that i got 3 printed for both 'a' and 'value'.
I got the above result on Lubuntu 14.04 with GCC 4.8.2 using the -std=c99 flag.
Thank you for anyone clearing me up on this matter!
The conditional operator does not "evaluate right to left". The standard (C11 6.5.15/4) says:
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)
So the expression (a == 3) ? 3 : (a = 3) ? 5 : 0; evaluates in these steps:
(a == 3) result is 0
(a = 3) result is 3, unequal to 0
5
So 5 is what is assigned to value.
You might be confusing the concept of how the conditional operator is evaluated with how the conditional operator associates (or groups). The syntax of C specifies that the expression:
(a == 3) ? 3 : (a = 3) ? 5 : 0;
associates or groups sub expressions like so:
((a == 3) ? 3 : ((a = 3) ? 5 : 0));
which is often described as 'associates right'. However, this grouping/associativity doesn't affect the fact that the expression is still evaluated left-to-right and that the second conditional expression only evaluates after the first operand in the 'outer' conditional expression is evaluated.
Let's trace through this one part at a time. You have this expression:
value = (a == 3) ? 3 : (a = 3) ? 5 : 0;
Since a starts off at 0, we skip the 3 branch of the first ?: and look at the second branch, which is
(a = 3) ? 5 : 0
The condition here is a = 3, which sets a to 3 and then evaluates to the new value of a, which is 3. Since 3 is nonzero, we take the first branch of the ?:, so the expression evaluates to 5. The net effect is that a is set to 3 and value is set to 5.
The language spec guarantees that the evaluation order is indeed what you think it should be - the "if" and "else" branches of the ?: operator are guaranteed not to execute unless the condition works out as it does, so there are sequence points here. I think you just misunderstood the effect of the a = 3 operation.
Hope this helps!
The conditional operator evaluates left-to-right (evaluating the condition before either of the branches). You may be confusing this with its right-associativity (in which it appears to bind right-to-left).
Your conditional expression essentially results in the following logic:
if(a == 3) {
value = 3;
} else {
if(a = 3) {
value = 5;
} else {
value = 0;
}
}
Note that the conditional doesn't execute a branch until after the condition is evaluated.

syntax of comparison between two different things

Following program gives error
#include<stdio.h>
int main ()
{
int a=10,b;
a>=5?b=100:b=200;
printf("\n%d",b);
}
the error is
ka1.c: In function ‘main’:
ka1.c:5: error: lvalue required as left operand of assignment
now if I replace the line
a>=5?b=100:b=200;
by
a>=5?b=100:(b=200);
and then compile then there is no error.
So I wanted to know what is wrong with
a>=5?b=100:b=200;
The ternary operator (?:) has higher precedence than the assignment operator (=). So your original statement is interpreted as:
((a >= 5) ? (b = 100) : b) = 200;
Write it like this instead:
b = (a >= 5) ? 100 : 200;
This is idiomatic C. (The brackets around the condition are not really necessary, but they aid readability.)
You're using the ternary operator incorrectly. Both of your examples are wrong, even though one compiles. The expression evaluates to either the second or third sub-expression depending upon the truth value of the first.
So a ? b : c will be the same thing as b if a is true, or c if a is false.
The proper way of using this operator is to assign the result to a variable:
b = a>= 5 ? 100 : 200;
Because it tries to do: (a>=5?b=100:b)=200
But the thing in parentheses is not lvalue.

Resources