What is the name of this C++ functionality? - c++

I was writing some C++ code and mistakenly omitted the name of a function WSASocket. However, my compiler did not raise an error and associated my SOCKET with the integer value 1 instead of a valid socket.
The code in question should have looked like this:
this->listener = WSASocket(address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);
But instead, it looked like this:
this->listener = (address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);
Coming from other languages, this looks like it may be some kind of anonymous type. What is the name of the feature, in the case it is really a feature?
What is its purpose?
It's difficult to search for it, when you don't know where to begin.

The comma operator† evaluates the left hand side, discards its value, and as a result yields the right hand side. WSA_FLAG_OVERLAPPED is 1, and that is the result of the expression; all the other values are discarded. No socket is ever created.
† Unless overloaded. Yes, it can be overloaded. No, you should not overload it. Step away from the keyboard, right now!

The comma operator is making sense of your code.
You are effectively setting this->listener = WSA_FLAG_OVERLAPPED; which just happens to be syntatically valid.

The compiler is evaluating each sequence point in turn within the parenthesis and the result is the final expression, WSA_FLAG_OVERLAPPED in the expression.
The comma operator , is a sequence point in C++. The expression to the left of the comma is fully evaluated before the expression to the right is. The result is always the value to the right. When you've got an expression of the form (x1, x2, x3, ..., xn) the result of the expression is always xn.

Related

dot operator order of evaluation in c++

I am reading "C++ Primer (5th Edition)" and I've run in something I'm not sure I understand correctly.
The example is pretty much similar to one they gave in the book. Imagine we have some function that returns string (or any class that has non-static members):
string some_function(par1, par2) {
string str;
// some code
return str;
}
I know that you can use the return value of any function to access its members, i.e. something like this is valid:
auto size = some_function(arg1, arg2).size(); // or whatever member of class
However, since the dot operator . and function call operator () have left to right grouping and same precedence, the above expression should be something like this:
(some_function(arg1, arg2)).size()
I suppose I am right so far? The thing I don't understand here is order of evaluation. Since order of evaluation is not specified for . operator, it means that either some_function(arg1, arg2) or size() will be evaluated first. But how can it evaluate size() first if it doesn't know on which object is it working on? This implies that order of evaluation should be fixed from left to right, but it is not. How is this possible?
Another example is something like this:
cin.get().get();
Again, it seems like first cin.get() should be evaluated before second get() since it won't know on which object is it working, but this doesn't seem to be necessarily the case.
Operators of the same precedence are evaluated according to their associativity, which you correctly observe is left-to-right for the operator group containing the function call and element selection operators. Therefore, yes, given the expression
x = foo().bar();
The order of operations is
x = (((foo()).bar)());
accounting for relative precedence and associativity of all operators involved. No one writes code in that manner, though.
Likewise, given
cin.get().get()
the order of operations is
(((cin.get)()).get)()
, so yes, the precedence rules result in the cin.get() sub-expression being evaluated first, yielding the object to which the second . (and thence the rest of the expression) is applied.

Left and Right operand of comma operator has no effect (Warning)

I'm getting a warning in my constructor in my class, and I've never seen it before. This is what my constructor looks like.
Account(std::string n = "NULL", std::string i = "0", Stats s = (0,0,1) )
: name(n), id(i), stat(s) {}
If I remove any of these commas it results in a compile error, no?
Is this warning incorrect, or is there something I can change to fix it?
The issue is this: (0,0,1).
That is parentheses around the expression 0,0,1, which evaluates to 1. (The comma operator is an infix operator that evaluates the first and second expression and returns the second. In this case, you have two such operators.)
I don't know what you wanted there, but I'm guessing that isn't it.
EDIT: It seems you want Stats s(0,0,1).
The problem is most likely in that part Stats s = (0,0,1). C++ sees this as a sequence of expression to be computed while keeping only the last value. It returns 1. You probably mean
Stats s = Stats(0,0,1)
which works if your stats structure have such a constructor. Note that in C++11 you have this shorter syntax:
Stats s = {0,0,1}
I think what you are looking for is to give a default value to function argument which is a struct, and I think it was discussed here How can I assign a default value to a structure in a C++ function?

Explain the difference:

int i=1,2,3,4; // Compile error
// The value of i is 1
int i = (1,2,3,4,5);
// The value of i is 5
What is the difference between these definitions of i in C and how do they work?
Edit: The first one is a compiler error. How does the second work?
= takes precedence over ,1. So the first statement is a declaration and initialisation of i:
int i = 1;
… followed by lots of comma-separated expressions that do nothing.
The second code, on the other hand, consists of one declaration followed by one initialisation expression (the parentheses take precedence so the respective precedence of , and = are no longer relevant).
Then again, that’s purely academic since the first code isn’t valid, neither in C nor in C++. I don’t know which compiler you’re using that it accepts this code. Mine (rightly) complains
error: expected unqualified-id before numeric constant
1 Precedence rules in C++ apply regardless of how an operator is used. = and , in the code of OP do not refer to operator= or operator,. Nevertheless, they are operators as far as C++ is concerned (§2.13 of the standard), and the precedence of the tokens = and , does not depend on their usage – it so happens that , always has a lower precedence than =, regardless of semantics.
You have run into an interesting edge case of the comma operator (,).
Basically, it takes the result of the previous statement and discards it, replacing it with the next statement.
The problem with the first line of code is operator precedence. Because the = operator has greater precedence than the , operator, you get the result of the first statement in the comma chain (1).
Correction (thanks #jrok!) - the first line of code neither compiles, nor is it using the comma as an operator, but instead as an expression separator, which allows you to define multiple variable names of the same type at a time.
In the second one, all of the first values are discarded and you are given the final result in the chain of items (5).
Not sure about C++, but at least for C the first one is invalid syntax so you can't really talk about a declaration since it doesn't compile. The second one is just the comma operator misused, with the result 5.
So, bluntly, the difference is that the first isn't C while the second is.

Comma operator in a conditional

I have read in a lot of places but I really can't understand the specified behavior in conditionals.
I understand that in assignments it evaluates the first operand, discards the result, then evaluates the second operand.
But for this code, what it supposed to do?
CPartFile* partfile = (CPartFile*)lParam;
ASSERT( partfile != NULL );
bool bDeleted = false;
if (partfile,bDeleted)
partfile->PerformFileCompleteEnd(wParam);
The partfile in the IF was an unnecessary argument, or it have any meaning?
In this case, it is an unnecessary expression, and can be deleted without changing the meaning of the code.
The comma operator performs the expression of the first item, discards the results, then evaluates the result as the last expression.
So partfile,bDeleted would evaulate whatever partfile would, discard that result, then evaluate and return bDeleted
It's useful if you need to evaluate something which has a side-effect (for example, calling a method). In this case, though, it's useless.
For more information, see Wikipedia: Comma operator
bool bDeleted = false;
if (partfile,bDeleted)
partfile->PerformFileCompleteEnd(wParam);
Here, the if statement evaluates partfile,bDeleted, but bDelete is always false, so the expression fails to run. The key question is "what's that all about?". The probable answer is that someone temporarily wanted to prevent the partfile->PerformFileCompleteEnd(wParam); statement from running, perhaps because it was causing some problem or they wanted to ensure later code reported errors properly if that step wasn't performed. So that they're remember how the code used to be, they left the old "if (partfile)" logic there, but added a hardcoded bDeleted variable to document that the partfile->Perform... logic had effectively been "deleted" from the program.
A better way to temporarily disable such code is probably...
#if 0
if (partfile)
partfile->PerformFileCompleteEnd(wParam);
#endif
...though sometimes I try to document the reasoning too...
#ifndef DONT_BYPASS_FILE_COMPLETE_PROCESSING_DURING_DEBUGGING
if (partfile)
partfile->PerformFileCompleteEnd(wParam);
#endif
...or...
if (partFile, !"FIXME remove this after debugging")
partfile->PerformFileCompleteEnd(wParam);
The best choice depends on your tool set and existing habits (e.g. some editors highlight "FIXME" and "TODO" in reverse video so it's hard to miss or grey out #if 0 blocks; you might have particular strings your source-control checkin warns about; preprocessor defines only in debug vs release builds can prevent accidental distribution etc.).
partfile is evaluated, then bDeleted is evaluated and used as the test. Since evaluation of partfile does not have any side effects, removing it from the conditional has no effect.
The comma operator is a rather obscure feature of C/C++. It should not be confused with the comma in initialising lists (ie: int x, int y; ) nor with function call parameter separation comma (ie: func(x, y) ).
The comma operator has one single purpose: to give the programmer a guaranteed order of evaluation of an expression. For almost every operator in C/C++, the order of evaluation of expressions is undefined. If I write
result = x + y;
where x and y are subexpressions, then either x or y can be evaluated first. I cannot know which, it's up to the compiler. If you however write
result = x, y;
the order of evaluation is guaranteed by the standard: left first.
Of course, the uses of this in real world applications are quite limited...

"x = ++x" is it really undefined?

I am using Coverity Prevent on a project to find errors.
It reports an error for this expression (The variable names are of course changed):
x=
(a>= b) ?
++x: 0;
The message is:
EVALUATION_ORDER defect: In "x=(a>= b) ? ++x: 0;", "x" is written in "x" (the assignment LHS) and written in "(a>= b) ? ++x: 0;" but the order in which the side effects take place is undefined because there is no intervening sequence point. END OF MESSAGE
While I can understand that "x = x++" is undefined, this one is a bit harder for me. Is this one a false positive or not?
Conditional operator ?: has a sequence point between evaluation of the condition (first operand) and evaluation of second or third operand, but it has no dedicated sequence point after the evaluation of second or third operand. Which means that two modifications of x in this example are potentially conflicting (not separated by a sequence point). So, Coverity Prevent is right.
Your statement in that regard is virtually equivalent to
a >= b ? x = ++x : x = 0;
with the same problem as in x = ++x.
Now, the title of your question seems to suggest that you don't know whether x = ++x is undefined. It is indeed undefined. It is undefined for the very same reason x = x++ is undefined. In short, if the same object is modified more than once between a pair of adjacent sequence points, the behavior is undefined. In this case x is modified by assignment and by ++ an there's no sequence point to "isolate" these modifications from each other. So, the behavior is undefined. There's absolutely no difference between ++x and x++ in this regard.
Regardless of the accuracy of the message, replacing the code in question by x= (a>= b) ? x+1: 0; achieves the same end without any confusion. If the tool is confused then maybe the next person to look at this code will be too.
This does assume that x does not have an overloaded increment operator with side-effects that you rely on here.
The statement x = ++x; writes to the variable x twice before hitting the sequence point and hence the behavior is undefined.
It is hard to imagine a compiler producing code for "x = ++x;" which would in fact not work the same as "++x". If x is not volatile, however, it would be legal for a compiler to process the statement "y = ++x;" as
y=x+1;
x=x+1;
The statement "x = ++x;" would thus become
x=x+1;
x=x+1;
If having the destination of one an arithmetic assignment expression get used too quickly as a source operand for another would cause a pipeline delay, the former optimization might be reasonable. Obviously disastrous if the incremented and assigned variable are one and the same.
If variable 'x' is volatile, I can't think of any code sequence where a compiler that wasn't deliberately trying to be mean could legitimately regard "x = x++;" as having any effect other than reading all parts of 'x' exactly once and writing the same correct value to all parts of 'x' exactly twice.
I suppose that logically, if you write either "x=++x" or "x=x++", either way you would expect the end result to be that x is one more than it started as. But make it just a shade more complicated. What if you wrote "x=x+(++x)" ? Is this the same as "x=x+(x+1)" ? Or do we add one first and then add x to itself, i.e. "x=(x+1)+(x+1)"? What if we wrote "x=(x--)+(x++)" ?
Even if you could write a language spec that gave unambiguous meaning to these sort of constructs, and could then implement it cleanly, why would you want to? Putting a unary increment in an assignment to the same variable just doesn't make sense, and even if we forced sense out of it, it provides no useful functionality. Like, I'm sure we could write a compliler that would take an expression like "x+1=y-1" and figure out that that really means "x=y-2", but why bother? There's no gain.
Even if we wrote compilers that did something predictable with "x=x++-++x", programmers would have to know and understand the rules. Without any obvious benefit, it would just add complexity to programs for no purpose.
In order to understand this you need to have a basic understanding of sequence points. See this link: http://en.wikipedia.org/wiki/Sequence_point
For the = operator there is no sequence point, so there is no guarantee that the value of x will be modified before it is again assigned to x.