Strange multiple assignment error in C++ - c++

I have multiple assignment statement in my program as shown below where query.constraints.size() is supposed to return 13 (constraints is an array and its returning its size)
int num,size = query.constraints.size();
When I do this size becomes 13 as expected but num becomes 9790272 for some reason.
When I do them separately as below everything is ok and both of them are 13 as expected
int size = query.constraints.size();
int num = query.constraints.size();
Why does my multiple assignment result in a strange a strange value ?

Why does my multiple assignment result in a strange a strange value ?
Because C++ has no multiple assignment1. You are declaring two variables here, but only initialise the second, not the first.
1 Well, you can do int a, b = a = c; but code which does this would be deemed bad by most C++ programmers except in very peculiar circumstances.

You're not assigning multiple times, you're declaring multiple times. You need to do something like:
int num, size;
size = num = query.constraints.size();

A mutiple assignement would looks like:
int num, size;
num = size = query.constraints.size();
But the comma operator does not do a multiple assignement.

What you have is actually a declaration statement, partially with initializer. Your code is equivalent to this code:
int num; // uninitialized, you're not allowed to read it
int size(query.constraints.size()); // initialized
In general, T x = expr; declares a variable x of type T and copy-initializes it with the value of expr. For fundamental types this just does what you expect. For class-types, the copy-constructor is only formally required, but in practice usually elided.

The comma operator doesnt do what you think it does

Related

Why is the following code illegal in C++ [duplicate]

This question already has answers here:
Declaring and initializing a variable in a Conditional or Control statement in C++
(9 answers)
Closed 7 years ago.
I want to create an if where a variable is declared, assigned and checked. If the variable's value is acceptable, I want to use it inside if body. Here's an example of how I thought I could do that:
if ((int result = Foo()) != 0) {
// use result
}
I assumed that Foo() returns some value, which is assigned to result, and returned by assignment operator =, and finally checked against 0 in != 0. Unfortunately, it results in a compilation error:
main.cpp:31:10: error: expected primary-expression before ‘int’
if ((int i = Foo()) != 0)
^
main.cpp:31:10: error: expected ‘)’ before ‘int’
Why is this error happening? And what ways could there be to fix it?
The logic is supported, but declaring a variable within an if statement and using it this way is not. The reason is related to the fact that an initializer works differently than a regular assignment, but working around this is easy and trivial.
Just do something like this instead.
int result;
if ((result = Foo()) != 0) {
// use result
}
Your reasoning seems to be based on the assumption that = in
if ((int result = Foo()) != 0)
is an assignment operator and that int result = Foo() is "just an expression" that evaluates to something.
This is not true.
The int result = Foo() part is not an expression in C++. It is a declaration with an initializer. The = in initializer syntax is not an assignment operator at all. It is just a syntactic element that coincidentally uses the same character as assignment operator. The int result = Foo() is not an expression and it does not "evaluate" to any result.
Because if the above, support for something like
if (int result = Foo())
requires special treatment, which severely limits the flexibility of this syntax. What you tried in your code goes outside the bounds of what's allowed by that special treatment.
Bjarne uses this construct as a scope restrictor in 6.3.2.1 The C++ programming language as a recommendation.
Use:
if (int result = Foo()) {
// use non-zero result
}
It is particularly useful with pointers
if (Foo* result = GetFoo()) {
// use valid Foo
}
The !=0 part is redundant as truthiness is !=0.
The extended construct with the comparison is not allowed.
Further discussion of this construct from here
It fails because it's illegal. It's also ugly. #Jonathan Wood suggested declaring the variable outside the if. I suggest calling Foo outside, too:
int result = Foo();
if(result!=0) ...
The (x=f())!=y construct, while legal as an if condition, only makes sense in a loop, where
`while((c=getchar())!='\n)
... do something with c ...
Is the shorter and nicer equivalent of
c = getchar();
while(c!='\n')
{
...
c = getchar(c);
}
It saves writing the call to getchar() twice. It saves nothing when used in an if, so there's no point in using it.
Try this:
if ( int i = (Foo() != 0) ? Foo() : 0 ){
cout << "Hello. Number i = " << i;
}

Using assignment operator in the parameter of a function call

I am a beginner at c++ can anyone explain me this code:
#include <iostream>
void display(int b)
{
std::cout << b << std::endl;
}
int main()
{
int a;
display(a=10);//display 10
std::cout << a << std::endl;//also display 10
return 0;
}
I know we can use = operator to set default values for a function parameters, but here it's in the function call, apparently "disply(a=10)" pass the value 10 to the function and store it in the variable "a" at the sametime.
is this correct coding in c++ and can anyone explain the assignment part?
The line
display(a=10);//display 10
equals to:
a = 10;
display(a);
This is because the value of the clause a = 10; is a.
I think this answers your question.
You need to know about = operator more. Not only is it assign rhs (right hand side) value to lhs (left hand side), but also it refers to the lhs.
Suppose this code:
a = b = c;
is exactly equal to
a = (b = c);
because = is right-associative.
If c is 10, the code assign 10 into b, and assign the value of b into a. So now a == b == c == 10.
The built-in assignment operator =
is right-associative
which means it groups to right, e.g. a = b = c means a = (b = c),
is an lvalue expression that refers to the left hand side.
Note that in C an assignment produces a pure value, while in C++ it produces a reference (in the common language meaning of referring).
This means that you can assign a value to multiple variables:
a = b = c = 12345;
which is parsed as
a = (b = (c = 12345));
which first copies 12345 to c, then copies c to b, then copies b to a.
And it means that you can assign to the result of an assignment:
((a = b) = c) = 12345;
which first copies the b value to a, then copies the c value to a, then copies 12345 to a, leaving b and c unchanged…
In your case, the code
display(a=10);
is equivalent to
a = 10; display( a );
Since the display function takes an int by value, this is equivalent to
display( 10 )
but if display had a reference argument then it could not be rewritten this way.
A common pitfall is to write
if( x = 12345 )
when one means to do a comparison,
if( x == 12345 )
Many compilers will warn about the first if the warning level is upped, as it should be.
More guaranteed ways to detect it include
Using const everywhere it can be used.
x can’t be assigned to when it’s const. This is my preferred solution.
Writing if( 12345 == x ).
Some people prefer this, but I find it hard to read, and as opposed to const it only helps to avoid the mis-typing when the writer is already, at that very point, very aware of the problem.
Defining a custom if construct via a macro.
Technically this works, also for other constructs that use boolean conditions, but in order to be useful such a macro should be short, and this runs the risk of name collision. It's also hard on maintainers who are unfamiliar with the (effectively) custom language.
In C++03 the standard library required that any container element type should be assignable, and the assignable criterion required that a custom assignment operator T::operator= should return T& (C++03 §23.1/4) – which is also a requirement on the built-in assignment operator.
Until I learned that I used to define assignment operators with result type void, since I saw no point in supporting coding of expressions with side-effects (which is generally a bad practice) at the cost of both efficiency and verbosity.
Unfortunately this is a case where in C++ you pay for what you don’t use and generally should not use.
The assignment <variable> = <value> in C, C++ is and expression which means it have a value and this value is, of course, the <value> you've just assigned.
That's the reason why you can assign a value to multiple variables like this:
a = b = c = 1;
because internally it works something like this
a = value of (b = value of (c = 1));
and since the assignment does indeed have a value, the value of (c = 1) is
1, value of (b = (c = 1)) is 1 and therefore we get a = 1. And as a
If the assignment wouldn't be an expression and didn't have a value, we would
get an error, because value of (c = 1) would not exist and we would get a
syntax error.
So in your code, display(a=10); means: *set value a to 10 and pass the
resulting value (which would be 10) as an argument to the function display.
It is correct.
display(a=10); //It assigns 10 to a and 10 is passed as the parameter to function.

How is this getting evaluated?

I am feeling very stupid to asking this question. but cant figure out the reason on my own.
int main()
{
int target;
int buffer =10;
const int source = 15;
target = (buffer+=source) = 20;
cout << target+buffer;
return 0;
}
target = (buffer+=source) = 20; will become target = (25) = 20.
But if I am giving same statement in my source file, it is giving l-value error.
How the value of target+buffer is printing 40.
Some predefined operators, such as +=, require an operand to be an
lvalue when applied to basic types [§13.5/7]
buffer+=source returns a lvalue reference to buffer. So you have not compile error.
your statement can be evaluate as:
buffer+=source;
buffer=20;
target=20;
But modifying buffer twice in a statement is undefined behavior and another compiler can evaluate something else as result. (Not sure in this case also!)

c++ strange syntax

i dont understand some things in a code from a tutorial
first one: what is that comma "," doing in the middle there? is it mb a overloaded operator?
u32 TimeStamp = irrTimer->getTime(), DeltaTime = 0;
next i have a weird constructor from class CharacterDemo, why is there a ":" following some variables with weird brackets? im guesseing they are beeing initialized with the value in the brackets.. ?
CharacterDemo::CharacterDemo()
:
m_indexVertexArrays(0),
m_vertices(0),
m_cameraHeight(4.f),
m_minCameraDistance(3.f),
m_maxCameraDistance(10.f)
{
m_character = 0;
m_cameraPosition = btVector3(30,30,30);
}
im rly curiouse, explanation much appriciated
It's an initialization list.
It calls the constructors of the members and parent classes of the specified class.
Note that you can only use it in the constructor of a class (because it only happens at its construction).
[edit] For your first question, it's a way to declare multiple variables of the same type at once. Note that it will not always work as expected : int * a, b will declare a variable a of type int *, and another variable b of type int (not a pointer).
what is that comma "," doing in the middle there?
A statement like int i = 3, j = 4; is the same as int i = 3; int j = 4;
So, u32 TimeStamp = irrTimer->getTime(), DeltaTime = 0; is defining and initializing two variables of type u32: one named TimeStamp and the other named DeltaTime.
why is there a ":" following some variables with weird brackets? im guesseing they are being initialized with the value in the brackets.. ?
That's correct: google for c++ member initialization list.

Using the comma operator in if statements

I tried the following:
if(int i=6+4==10)
cout << "works!" << i;
if(int i=6+4,i==10)
cout << "doesn't even compile" << i;
The first works fine while the second doesn't compile. Why is this?
EDIT: Now I know that the first one may not work as I intend it to. The value of i inside the if scope will be 1, not 10. (as pointed out by one of the comments on this question).
So is there a way to initialize and use a variable inside of an if statement at the same time similar to for(int i=0;i<10;i++)? So that you could produce something like if((int i=6+4)==10) (which will not compile) where the value of I inside the if scope would be 10?
I know you could declare and initialize I before the if statement but is there a way to do this within the statement itself?
To give you an idea why I think this would be usefull.
if(int v1=someObject1.getValue(), int v2=someObject2.getValue(), v1!=v2)
{
//v1 and v2 are visible in this scope
//and can be used for further calculation without the need to call
//someObject1.getValue() und someObject2.getValue() again.
}
//if v1==v2 there is nothing to be done which is why v1 und v2
//only need to be visible in the scope of the if.
The expression used as an initializer expression must be an assignment-expression so if you want to use a comma operator you must parenthesize the initializer.
E.g. (not that what you are attempting makes much sense as 6 + 4 has no side effects and the value is discarded and i == 10 uses the uninitialized value of i in its own initializer.)
if (int i = (6 + 4, i == 10)) // behaviour is undefined
Did you really mean something like this?
int i = 6 + 4;
if (i == 10)
When using the form of if that declares a new variable the condition checked is always the value of the initialized variable converted to bool. If you want the condition to be an expression involving the new variable you must declare the variable before the if statement and use the expression that you want to test as the condition.
E.g.
int i;
if ((i = 6 + 4) == 10)
I doubt seriously either example works to do anything useful. All that it does is evaluate to "true" in a complicated fashions.
But the reason the second one doesn't compile is that it's interpreted as two declarations: int i = 6+4; int i==10 and int i==10 isn't valid because that's an equality operator, not an assignment.
There are different alternatives, because what you want cannot be done (you cannot mix the comma operator with declarations). You could, for example, declare the variable outside of the if condition:
int i = 6+4;
if ( i == 10 ) ...
Or you can change the value of i to be 0 instead of 10 and recalculate i inside the else block:
if ( int i = (6+4)-10 ) ; else {
i += 10;
// ...
}
Much simpler, don't declare the variable at all, since you know the value inside the loop:
if ( (6+4)==10 ) {
int i = 10;
// ...
}
Unless of course you need the value of i in the case where it is not 10, in which case the second option is the most appropriate.
As of C++17 what you were trying to do is finally possible:
if (int i=6+4; i==10)
cout << "works, and i is " << i << endl;
Note the use of ; of instead of , to separate the declaration and the actual condition.