Why does an expression i = 2 return 2? What is the rule this is based on?
printf("%d\n", i = 2 ); /* prints 2 */
I am in C domain after spending long time in Java/C#. Forgive my ignorance.
It evaluates to 2 because that's how the standard defines it. From C11 Standard, section 6.5.16:
An assignment expression has the value of the left operand after the assignment
It's to allow things like this:
a = b = c;
(although there's some debate as to whether code like that is a good thing or not.)
Incidentally, this behaviour is replicated in Java (and I would bet that it's the same in C# too).
The rule is to return the right-hand operand of = converted to the type of the variable which is assigned to.
int a;
float b;
a = b = 4.5; // 4.5 is a double, it gets converted to float and stored into b
// this returns a float which is converted to an int and stored in a
// the whole expression returns an int
It consider the expression firstly then print the leftmost variable.
example:
int x,y=10,z=5;
printf("%d\n", x=y+z ); // firstly it calculates value of (y+z) secondly puts it in x thirdly prints x
Note:
x++ is postfix and ++x is prefix so:
int x=4 , y=8 ;
printf("%d\n", x++ ); // prints 4
printf("%d\n", x ); // prints 5
printf("%d\n", ++y ); // prints 9
Assign the value 2 to i
Evaluate the i variable and display it
In C (almost) all expressions have 2 things
1) a value
2) a side effect
The value of the expression
2
is 2; its side effect is "none";
The value of the expression
i = 2
is 2; its side effect is "changing the value in the object named i to 2";
Related
I saw a program in C that had code like the following:
static void *arr[1] = {&& varOne,&& varTwo,&& varThree};
varOne: printf("One") ;
varTwo: printf("Two") ;
varThree: printf("Three") ;
I am confused about what the && does because there is nothing to the left of it. Does it evaluate as null by default? Or is this a special case?
Edit:
Added some more information to make the question/code more clear for my question.
Thank you all for the help. This was a case of the gcc specific extension.
It's a gcc-specific extension, a unary && operator that can be applied to a label name, yielding its address as a void* value.
As part of the extension, goto *ptr; is allowed where ptr is an expression of type void*.
It's documented here in the gcc manual.
You can get the address of a label defined in the current function (or
a containing function) with the unary operator &&. The value has
type void *. This value is a constant and can be used wherever a
constant of that type is valid. For example:
void *ptr;
/* ... */
ptr = &&foo;
To use these values, you need to be able to jump to one. This is done
with the computed goto statement, goto *exp;. For example,
goto *ptr;
Any expression of type void * is allowed.
As zwol points out in a comment, gcc uses && rather than the more obvious & because a label and an object with the same name can be visible simultaneously, making &foo potentially ambiguous if & means "address of label". Label names occupy their own namespace (not in the C++ sense), and can appear only in specific contexts: defined by a labeled-statement, as the target of a goto statement, or, for gcc, as the operand of unary &&.
This is a gcc extension, known as "Labels as Values". Link to gcc documentation.
In this extension, && is a unary operator that can be applied to a label. The result is a value of type void *. This value may later be dereferenced in a goto statement to cause execution to jump to that label. Also, pointer arithmetic is permitted on this value.
The label must be in the same function; or in an enclosing function in case the code is also using the gcc extension of "nested functions".
Here is a sample program where the feature is used to implement a state machine:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
void *tab[] = { &&foo, &&bar, &&qux };
// Alternative method
//ptrdiff_t otab[] = { &&foo - &&foo, &&bar - &&foo, &&qux - &&foo };
int i, state = 0;
srand(time(NULL));
for (i = 0; i < 10; ++i)
{
goto *tab[state];
//goto *(&&foo + otab[state]);
foo:
printf("Foo\n");
state = 2;
continue;
bar:
printf("Bar\n");
state = 0;
continue;
qux:
printf("Qux\n");
state = rand() % 3;
continue;
}
}
Compiling and execution:
$ gcc -o x x.c && ./x
Foo
Qux
Foo
Qux
Bar
Foo
Qux
Qux
Bar
Foo
I'm not aware of any operator that works this way in C.
Depending on the context, the ampersand in C can mean many different things.
Address-Of operator
Right before an lvalue, e.g.
int j;
int* ptr = &j;
In the code above, ptr stores the address of j, & in this context is taking the address of any lvalue. The code below, would have made more sense to me if it was written that way.
static int varOne;
static int varTwo;
static int varThree;
static void *arr[1][8432] = { { &varOne,&varTwo, &varThree } };
Logical AND
The logical AND operator is more simple, unlike the operator above, it's a binary operator, meaning it requires a left and right operand. The way it works is by evaluating the left and right operand and returning true, iff both are true, or greater than 0 if they are not bool.
bool flag = true;
bool flag2 = false;
if (flag && flag2) {
// Not evaluated
}
flag2 = true;
if (flag && flag2) {
// Evaluated
}
Bitwise AND
Another use of the ampersand in C, is performing a bitwise AND. It's similar as the logical AND operator, except it uses only one ampersand, and performs an AND operation at the bit level.
Let's assume we have a number and that it maps to the binary representation shown below, the AND operation works like so:
0 0 0 0 0 0 1 0
1 0 0 1 0 1 1 0
---------------
0 0 0 0 0 0 1 0
In C++ land, things get more complicated. The ampersand can be placed after a type as to denote a reference type (you can think of it as a less powerful but safe kind of pointer), then things get even more complicated with 1) r-value reference when two ampersands are placed after a type. 2) Universal references when two ampersands are placed after a template type or auto deducted type.
I think your code probably compiles only in your compiler due to an extension of some sorts. I was thinking of this https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C but I doubt that's the case.
Consider the following snippets:
C++:
#include <iostream>
using namespace std;
int main()
{
int x = 10, y = 20;
y = x + (x=y)*0;
cout << y;
return 0;
}
which gives a result of 20, because the value of y is assigned to x since the bracket is executed first according to the Operator Precedence Table.
VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As Integer = 10
Dim y As Integer = 20
y = x + (x = y) * 0
MsgBox(y)
End Sub
which instead gives a result of 10.
What is the reason for this difference?
What is the order of execution of operators in VB.NET?
Unlike in C++, VB.NET's = is not always an assignment. It can also be the equality comparison operator (== in C++) if it appears inside an expression. Therefore your two expressions are not the same. They are not even equivalent. The VB.NET code does not do what you might think it does.
First to your C++ code: Like you're saying, the assignment x=y happens first; thus your code is roughly equivalent to this: (It seems that was incorrect; see Jens' answer.) Since you end up with y being 20, it is likely that your C++ compiler evaluated your code as if you had written this:
int x = 10, y = 20;
x = y;
y = x + x*0; // which is equivalent to `y = 20 + 20*0;`, or `y = 20 + 0;`, or `y = 20;`
In VB.NET however, because the = in your subexpression (x=y) is not actually interpreted as an assignment, but as a comparison, the code is equivalent to this:
Dim x As Integer = 10
Dim y As Integer = 20
y = 10 + False*0 ' which is equivalent to `y = 10 + 0*0`, or `y = 10` '
Here, operator precedence doesn't even come into play, but an implicit type conversion of the boolean value False to numeric 0.
(Just in case you were wondering: In VB.NET, assignment inside an expression is impossible. Assignments must always be full statements of their own, they cannot happen "inline". Otherwise it would be impossible to tell whether a = inside an expression meant assignment or comparison, since the same operator is used for both.)
Your C++ snippet is undefined behavior. There is no sequence point between using x as the first argument and assigning y to x, so the compiler can evaluate the sub-expressions in any order. Both
First evaluate the left side: y = 10 + (x=y) * 0 -> y = 10 + (x=20) * 0 -> y = 10 + 20*0
First evaluate the right side: y = x + (x=20) * 0 -> y = 20 + 20 * 0
It is also generally a very bad style to put assignments inside expressions.
This answer was intended as a comment, but its length quickly exceeded the limit. Sorry :)
You are confusing operator precedence with evaluation order. (This is a very common phenomenon, so don't feel bad). Let me try to explain with a simpler example involving more familiar operators:
If you have an expression like a + b * c then yes, the multiplication will always happen before the addition, because the * operator binds tighter than + operator. So far so good? The important point is that C++ is allowed to evaluate the operands a, b and c in any order it pleases. If one of those operands has a side effect which affects another operand, this is bad for two reasons:
It may cause undefined behavior (which in your code is indeed the case), and more importantly
It is guaranteed to give future readers of your code serious headaches. So please don't do it!
By the way, Java will always evaluate a first, then b, then c, "despite" the fact that multiplication happens before addition. The pseudo-bytecode will look like push a; push b; push c; mul; add;
(You did not ask about Java, but I wanted to mention Java to give an example where evaluating a is not only feasible, but guaranteed by the language specification. C# behaves the same way here.)
I have a pointer which is defined as follows:
A ***b;
What does accessing it as follows do:
A** c = b[-1]
Is it an access violation because we are using a negative index to an array? Or is it a legal operation similar to *--b?
EDIT Note that negative array indexing has different support in C and C++. Hence, this is not a dupe.
X[Y] is identical to *(X + Y) as long as one of X and Y is of pointer type and the other has integral type. So b[-1] is the same as *(b - 1), which is an expression that may or may not be evaluated in a well-formed program – it all depends on the initial value of b! For example, the following is perfectly fine:
int q[24];
int * b = q + 13;
b[-1] = 9;
assert(q[12] == 9);
In general, it is your responsibility as a programmer to guarantee that pointers have permissible values when you perform operations with them. If you get it wrong, your program has undefined behaviour. For example:
int * c = q; // q as above
c[-1] = 0; // undefined behaviour!
Finally, just to reinforce the original statement, the following is fine, too:
std::cout << 2["Good morning"] << 4["Stack"] << 8["Overflow\n"];
See the code
#include<iostream.h>
#include<conio.h>
class A{
private:
int i;
public:
A()
{
i=10;
}
A operator++(int)
{
A tmp=*this;
i +=1;
return tmp;
}
display()
{
cout<<i;
}
};
int main()
{
A a,b;
b=a++ + a++;
cout<<endl<<b<<"\t"<<a;
return 0;
}
For the statement b = a++ + a++, the expected value we think will be 20,
But the above statement resulted into 21.
How?
Kindly help me out.
According to cppreference, your code is equals to b = (a++) + (a++)
So, computing it, we have:
a = 10;
tmp1 = a++;//tmp1 = 10, a = 11
tmp2 = a++;//tmp2 = 11, a = 12
b = tmp1 + tmp2 // 10 + 11 = 21
Also remember that constructions like b = a++ + a++; are very poor readable, so you should always use brackets, also it's always a good idea to avoid using increments and decrements like a++ in complex expressions. Readability is much better than showing that you know operator priorities.
As Charles pointed out ++ called on A object are function calls. Thus you first increment i from 10 to 11 and return 10, then in the second call you increment i from 11 to 12 and return 11. The you add 10 and 11 ending up with 21.
The first call increments a to 11 and returns 10. The second call increments a to 12 and returns 11. Sounds like 21 is correct.
That said, the order of evaluation (which ++ is "the first call") is unspecified (thanks JD), so using it twice in the same expression is generally not a good idea.
I shall render my answer in the form of a simple comparison.
Your code is:
b = a++ + a++;
I think you rather confused it with:
b = a + (a++)++;
Overloaded operators are just functions with funny names. They don't neccesarily behave the same as built-in ones. If you're tempted to do the same expression with an object of built-in type - don't, the behaviour would be undefined.
You haven't shown the definition of operator+ for A - I'll asume it's a free function. The expression b = a++ + a++; can then be rewritten as
b = operator+( a.operator++(0), a.operator++(0) );
Hope that helps make things clearer.
The two calls to postfix increment are indeterminately sequenced - that means we can't know which one will be called first. It doesn't matter in your case, since they're both called on the same object, but don't rely on any particular order - it need not be consistent, even during the same execution of the program.
I thought that my understanding of side effects in programming languages was OK.
I think this is a great definition from wikipedia:
"in addition to returning a value, it also modifies some state or has
an observable interaction with calling functions or the outside world."
However, I read this in the same link(yes, I know that is probably not the best place to look for examples):
"One common demonstration of side effect behavior is that of the
assignment operator in C++. For example, assignment returns the right
operand and has the side effect of assigning that value to a variable.
This allows for syntactically clean multiple assignment:"
int i, j;
i = j = 3;
Why do they consider that a side-effect? It is the same as two simple assignment statements to 2 local variables.
Thanks in advance.
You can use an assignment expression as a value:
double d = 3.5;
int x, y;
printf("%d", x = d); // Prints "3".
y = (x = d) * 5; // Sets y to 15.
double z = x = d; // Sets z to 3 (not 3.5).
The value produced by x = d, is its main effect. The changing of the value of x is a side effect.
If the state of the world, for example the value of a variable, is modified in a calculation, it's a side effect.
For example, j = 3 calculates 3, but it also modifies the value of j as a side effect.
A less trivial example: j += 3 calculates j + 3, but it also sets j to this new value.
The semantics of C muddle the waters: in C the main point of writing i = 1 is to get the side effect of the variable assignment; not calculating the value 1. The talk about assignments as side effects makes more sense with functional programming languages such as Haskell or Erlang, where variables can only be assigned once.
I would presume that to be because j = 3 has the intended effect of assigning the value 3 to j but also has the side effect of returning the value of j