Using operator "/=" at 'declare&initialize' part - c++

I'm a student who got interested in computer science recently. I'm studying C++ because I am interested in embedded systems.
When I tried to test the operator /= on my own. I want to learn about it by doing. The code that I wrote was
int a /= --b + 3;
but the compiler gave me an error message. But when I modified it to
int a = 0;
a /= --b + 3;`
it worked well. I thought it is related to l-values and r-values. Why does the 1st example with operator /= give me an error but the 2nd example above is ok? Can I ask you for some reference to get a hint about this question?
PS: When I tested with
int t = t / (--a + 3);
it worked well too! What is the difference? Can you point me to some document about that?

I would like to mention two things.
What is the meaning of this code?
Is it valid C++ syntax?
Let's take a look at both.
when I tested "int a/=--b+3", it has error but when I modified to "int a=0;
a/=--b+3;" , it works well.
Unlike Java, C/C++ does not automatically initialize integer's value by 0 and it contains a garbage value(called "indeterminate value" officially). So int a/=--b+3; is more like int a; a/=--b+3; which is still be a meaningless value.
And when you declare a variable, C/C++ grammar does not allow /=. Here are the ways for variable declaration and initialization. I'm not sure there is more ways.
int a = 1;
int a(1);
int a{1}; (since C++11)

a /= b;
is the same as:
a = a / b;
so this means that this below statement makes no sense:
int a /= (--b + 3);
Because it's equivalent to:
int a = a / (--b + 3);
Assuming that b has already been defined here; the problem is that a hasn't been defined, and so can't be used as part of the assignment.
The problem here is the same as the problem with this statement:
int a = a;
This also explains why the following code does work:
int a = 0;
a /= (--b + 3);
Because it's equivalent to this:
int a = 0;
a = a / (--b + 3);
Because a is known in the second line above, the RHS can be defined, and the new value for a determined.
More generally, operators like /=, *=, +=, -= and %= shouldn't be used during initialisation of a variable. A compiler (such as g++) should respond with an error if you ever try to do this.

Related

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.

Arithmetic operation with a void?

I know that the following, if possible, would be an absolutely bad practice, but I want to know if this is possible.
The question is the following: is it possible in C++ (and in a way the compiler does not throw any warning), to perform a useless arithmetic operation with a function returning a void.
std::vector<int> v;
int i = 42 + v.resize(42);
/* How to transform the last line to execute resize and to have i = 42 */
I know that this is stupid, but that is not the question...
I'm not sure it makes much sense, but you could use the comma operator here:
int i = (v.resize(42), 42);
You could use the comma operator:
int i = (v.resize(42), 42);
and with GCC you could use its statement expression extension:
int i = ({v.resize(42); 42;})
and in standard C++11 you could use and call an anonymous closure:
int i = ([&v]() {v.resize(42); return 42;}());
Type void has no values so it may not be used in arithmetic expressions.
In my opinion the design of member function resize is bad. Instead of voidit should return the object itself. In this case you could write for example
int i = v.resize(42).size();
I pointed out about this in the forum where the C++ Standard is discussed.
As for your question then you can write
int i = ( v.resize(42), v.size() );
using the comma operator.
Or maybe it would be better to separate these two calls
v.resize(42);
int i = v.size();
Don't see the point, but here's another way
std::tie(i, std::ignore) = std::make_tuple(42, (v.resize(42),1) );
Also you can do:
if ((i=42)) v.resize(42);
And don't forget
do { v.resize(42); } while (!(i=42));
And the favorite
(i=42) ? v.resize(42) : i;
Or (the only serious c++ in the post)
int i(0);
std::vector<int> v(i=42);
Come on, this has no end
.....

What is the meaning and name for "+=" in C++?

I am fairly new to C++ and I have been reading and writing some of my own code. I see these operators from time to time, if that is even the right word to use?
+= // Not sure what it means
So my question is: what do they mean/do, and what are they called?
For further reference, I'd like to know what they are called so I can easily look it up (searching simply for "+=" for instance yielded nothing).
Edit: For anyone else who does not know the meaning (or in my case knew the name of these) I found this Wikipedia link which might come of handy to other people: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
Yes, these are operators. More specifically, they are known as compound assignment operators. Here's the full list of them:
*= /= %= += -= >>= <<= &= ^= |=
They are defined like so:
The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
So x += 5; is almost the same as x = x + 5;.
You can think of it as a modifying addition. If you just do x + 5, the result of the expression is what you get if you add x and 5 together, but x hasn't changed. If you do x += 5;, x actually has 5 added to its value.
its just an abbreviation:
a+=2; means a=a+2;
of course as many operators: you can overload it to give it alternative meaning, ans actually we do it often to provide meaning for example in the case what it means to add int to our class SomeClass:
SomeClass s;
s+=1; //operator+=(SomeClass& s, int i){} is used here
class A{
public:
A():i_(123){}
~A(){}
int i(){return i_;}
A const& operator+=(int i){
std::cout<<"operator+=";
this->i_=i_+i;
}
private:
int i_;
};
int main(int argc, char** argv) {
A a1;
a1+=3;
std::cout<<a1.i();
return OK;
}
output: operator+=126

Strange multiple assignment error in 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

Uses of C comma operator [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 8 years ago.
You see it used in for loop statements, but it's legal syntax anywhere. What uses have you found for it elsewhere, if any?
C language (as well as C++) is historically a mix of two completely different programming styles, which one can refer to as "statement programming" and "expression programming". As you know, every procedural programming language normally supports such fundamental constructs as sequencing and branching (see Structured Programming). These fundamental constructs are present in C/C++ languages in two forms: one for statement programming, another for expression programming.
For example, when you write your program in terms of statements, you might use a sequence of statements separated by ;. When you want to do some branching, you use if statements. You can also use cycles and other kinds of control transfer statements.
In expression programming the same constructs are available to you as well. This is actually where , operator comes into play. Operator , is nothing else than a separator of sequential expressions in C, i.e. operator , in expression programming serves the same role as ; does in statement programming. Branching in expression programming is done through ?: operator and, alternatively, through short-circuit evaluation properties of && and || operators. (Expression programming has no cycles though. And to replace them with recursion you'd have to apply statement programming.)
For example, the following code
a = rand();
++a;
b = rand();
c = a + b / 2;
if (a < c - 5)
d = a;
else
d = b;
which is an example of traditional statement programming, can be re-written in terms of expression programming as
a = rand(), ++a, b = rand(), c = a + b / 2, a < c - 5 ? d = a : d = b;
or as
a = rand(), ++a, b = rand(), c = a + b / 2, d = a < c - 5 ? a : b;
or
d = (a = rand(), ++a, b = rand(), c = a + b / 2, a < c - 5 ? a : b);
or
a = rand(), ++a, b = rand(), c = a + b / 2, (a < c - 5 && (d = a, 1)) || (d = b);
Needless to say, in practice statement programming usually produces much more readable C/C++ code, so we normally use expression programming in very well measured and restricted amounts. But in many cases it comes handy. And the line between what is acceptable and what is not is to a large degree a matter of personal preference and the ability to recognize and read established idioms.
As an additional note: the very design of the language is obviously tailored towards statements. Statements can freely invoke expressions, but expressions can't invoke statements (aside from calling pre-defined functions). This situation is changed in a rather interesting way in GCC compiler, which supports so called "statement expressions" as an extension (symmetrical to "expression statements" in standard C). "Statement expressions" allow user to directly insert statement-based code into expressions, just like they can insert expression-based code into statements in standard C.
As another additional note: in C++ language functor-based programming plays an important role, which can be seen as another form of "expression programming". According to the current trends in C++ design, it might be considered preferable over traditional statement programming in many situations.
I think generally C's comma is not a good style to use simply because it's so very very easy to miss - either by someone else trying to read/understand/fix your code, or you yourself a month down the line. Outside of variable declarations and for loops, of course, where it is idiomatic.
You can use it, for example, to pack multiple statements into a ternary operator (?:), ala:
int x = some_bool ? printf("WTF"), 5 : fprintf(stderr, "No, really, WTF"), 117;
but my gods, why?!? (I've seen it used in this way in real code, but don't have access to it to show unfortunately)
Two killer comma operator features in C++:
a) Read from stream until specific string is encountered (helps to keep the code DRY):
while (cin >> str, str != "STOP") {
//process str
}
b) Write complex code in constructor initializers:
class X : public A {
X() : A( (global_function(), global_result) ) {};
};
I've seen it used in macros where the macro is pretending to be a function and wants to return a value but needs to do some other work first. It's always ugly and often looks like a dangerous hack though.
Simplified example:
#define SomeMacro(A) ( DoWork(A), Permute(A) )
Here B=SomeMacro(A) "returns" the result of Permute(A) and assigns it to "B".
The Boost Assignment library is a good example of overloading the comma operator in a useful, readable way. For example:
using namespace boost::assign;
vector<int> v;
v += 1,2,3,4,5,6,7,8,9;
I had to use a comma to debug mutex locks to put a message before the lock starts to wait.
I could not but the log message in the body of the derived lock constructor, so I had to put it in the arguments of the base class constructor using : baseclass( ( log( "message" ) , actual_arg )) in the initialization list. Note the extra parenthesis.
Here is an extract of the classes :
class NamedMutex : public boost::timed_mutex
{
public:
...
private:
std::string name_ ;
};
void log( NamedMutex & ref__ , std::string const& name__ )
{
LOG( name__ << " waits for " << ref__.name_ );
}
class NamedUniqueLock : public boost::unique_lock< NamedMutex >
{
public:
NamedUniqueLock::NamedUniqueLock(
NamedMutex & ref__ ,
std::string const& name__ ,
size_t const& nbmilliseconds )
:
boost::unique_lock< NamedMutex >( ( log( ref__ , name__ ) , ref__ ) ,
boost::get_system_time() + boost::posix_time::milliseconds( nbmilliseconds ) ),
ref_( ref__ ),
name_( name__ )
{
}
....
};
From the C standard:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. (A comma operator does not yield an lvalue.)) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.
In short it let you specify more than one expression where C expects only one. But in practice it's mostly used in for loops.
Note that:
int a, b, c;
is NOT the comma operator, it's a list of declarators.
It is sometimes used in macros, such as debug macros like this:
#define malloc(size) (printf("malloc(%d)\n", (int)(size)), malloc((size)))
(But look at this horrible failure, by yours truly, for what can happen when you overdo it.)
But unless you really need it, or you are sure that it makes the code more readable and maintainable, I would recommend against using the comma operator.
You can overload it (as long as this question has a "C++" tag). I have seen some code, where overloaded comma was used for generating matrices. Or vectors, I don't remember exactly. Isn't it pretty (although a little confusing):
MyVector foo = 2, 3, 4, 5, 6;
Outside of a for loop, and even there is has can have an aroma of code smell, the only place I've seen as a good use for the comma operator is as part of a delete:
delete p, p = 0;
The only value over the alternative is you can accidently copy/paste only half of this operation if it is on two lines.
I also like it because if you do it out of habit, you'll never forget the zero assignment. (Of course, why p isn't inside somekind of auto_ptr, smart_ptr, shared_ptr, etc wrapper is a different question.)
Given #Nicolas Goy's citation from the standard, then it sounds like you could write one-liner for loops like:
int a, b, c;
for(a = 0, b = 10; c += 2*a+b, a <= b; a++, b--);
printf("%d", c);
But good God, man, do you really want to make your C code more obscure in this way?
It's very useful in adding some commentary into ASSERT macros:
ASSERT(("This value must be true.", x));
Since most assert style macros will output the entire text of their argument, this adds an extra bit of useful information into the assertion.
In general I avoid using the comma operator because it just makes code less readable. In almost all cases, it would be simpler and clearer to just make two statements. Like:
foo=bar*2, plugh=hoo+7;
offers no clear advantage over:
foo=bar*2;
plugh=hoo+7;
The one place besides loops where I have used it it in if/else constructs, like:
if (a==1)
... do something ...
else if (function_with_side_effects_including_setting_b(), b==2)
... do something that relies on the side effects ...
You could put the function before the IF, but if the function takes a long time to run, you might want to avoid doing it if it's not necessary, and if the function should not be done unless a!=1, then that's not an option. The alternative is to nest the IF's an extra layer. That's actually what I usually do because the above code is a little cryptic. But I've done it the comma way now and then because nesting is also cryptic.
I often use it to run a static initializer function in some cpp files, to avoid lazy initalization problems with classic singletons:
void* s_static_pointer = 0;
void init() {
configureLib();
s_static_pointer = calculateFancyStuff(x,y,z);
regptr(s_static_pointer);
}
bool s_init = init(), true; // just run init() before anything else
Foo::Foo() {
s_static_pointer->doStuff(); // works properly
}
For me the one really useful case with commas in C is using them to perform something conditionally.
if (something) dothis(), dothat(), x++;
this is equivalent to
if (something) { dothis(); dothat(); x++; }
This is not about "typing less", it's just looks very clear sometimes.
Also loops are just like that:
while(true) x++, y += 5;
Of course both can only be useful when the conditional part or executable part of the loop is quite small, two-three operations.
The only time I have ever seen the , operator used outside a for loop was to perform an assingment in a ternary statement. It was a long time ago so I cannot remeber the exact statement but it was something like:
int ans = isRunning() ? total += 10, newAnswer(total) : 0;
Obviously no sane person would write code like this, but the author was an evil genius who construct c statements based on the assembler code they generated, not readability. For instance he sometimes used loops instead of if statements because he preferred the assembler it generated.
His code was very fast but unmaintainable, I am glad I don't have to work with it any more.
I've used it for a macro to "assign a value of any type to an output buffer pointed to by a char*, and then increment the pointer by the required number of bytes", like this:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
Using the comma operator means the macro can be used in expressions or as statements as desired:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
It reduced some repetitive typing but you do have to be careful it doesn't get too unreadable.
Please see my overly-long version of this answer here.
It can be handy for "code golf":
Code Golf: Playing Cubes
The , in if(i>0)t=i,i=0; saves two characters.
qemu has some code that uses the comma operator within the conditional portion of a for loop (see QTAILQ_FOREACH_SAFE in qemu-queue.h). What they did boils down to the following:
#include <stdio.h>
int main( int argc, char* argv[] ){
int x = 0, y = 0;
for( x = 0; x < 3 && (y = x+1,1); x = y ){
printf( "%d, %d\n", x, y );
}
printf( "\n%d, %d\n\n", x, y );
for( x = 0, y = x+1; x < 3; x = y, y = x+1 ){
printf( "%d, %d\n", x, y );
}
printf( "\n%d, %d\n", x, y );
return 0;
}
... with the following output:
0, 1
1, 2
2, 3
3, 3
0, 1
1, 2
2, 3
3, 4
The first version of this loop has the following effects:
It avoids doing two assignments, so the chances of the code getting out of sync is reduced
Since it uses &&, the assignment is not evaluated after the last iteration
Since the assignment isn't evaluated, it won't try to de-reference the next element in the queue when it's at the end (in qemu's code, not the code above).
Inside the loop, you have access to the current and next element
Found it in array initialization:
In C what exactly happens if i use () to initialize a double dimension array instead of the {}?
When I initialize an array a[][]:
int a[2][5]={(8,9,7,67,11),(7,8,9,199,89)};
and then display the array elements.
I get:
11 89 0 0 0
0 0 0 0 0