The << and >> operators have two meanings in C++, bit-shifting and stream operations. How does the compiler resolve this ambiguity when the meaning isn't obvious from context? Take this line for example:
std::cout << 1 << 2 << std::endl;
Would the output be 12, as if the second << were treated as a stream insertion, or 4, as if the second << were treated as a bit shift?
operator >> and operator << have left to right associativity. That means that with the addition of some parentheses, the actual expression is
((std::cout << 1) << 2) << std::endl;
and here you can see that with each call, the stream object, or the return of the stream expression, is used as the left hand side of each expression. That means all of the values will inserted into the stream.
There is no ambiguity, because compilers interprets the expression from left to right, so this:
std::cout << 1 << 2 << std::endl;
is equivalent to:
((std::cout << 1) << 2) << std::endl;
Consider that << has left-to-right associativity (see here) and that
std::cout << 1 << 2 << std::endl;
can be thought of as the short way of writing:
std::cout.operator<<(1).operator<<(2).operator<<(std::endl);
In other words: There is no ambiguity.
PS: Also consider that the "problem" you see is not only about two meanings of <<. The operator can be overloaded to have any meaning for a custom type. Nevertheless std::cout << custom_object_1 << custom_object_2; calls std::ostream& operator<<(std::ostream&,const custom_type&). For example: https://godbolt.org/z/fn3PTz.
Related
I am currently working on a code and I am trying to use a if-statement on a variable which was taken from a .txt file with a basic string. Its supposed to look like
if (a.variable == "string") {}
When I use
std::cout << a.variable << std::endl;
std::cout << "string" << std::endl;
I get the same results but when using
std::cout << typeid(a.variable).name() << std::endl;
std::cout << typeid("string").name() << std::endl;
I get different results:
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
and
A5_c.
Could this be the reason why the if-statement failed? Unless I am incorrect, the first typeid stands for a basic string.
I am grateful for any input!
The code I use for reading it looks like:
std::string::size_type beginoption = section.find("=",position);
beginoption = beginoption +1;
std::string::size_type endoption = section.find("\n",position);
optionstorage = section.substr(beginoption, endoption - beginoption);
Two objects in C++ don't have to be the same type to compare as equal. You can compare string objects to string literals because there is an operator== overload that accepts std::string and char const * arguments. (The typeid() operator returns a different value because the two expressions have different types; one is a string object and the other is a char array -- but you can indeed still compare them.)
You mentioned that your "if statement is failing" but when you inspect the contents of the strings, they appear to be the same -- they may actually not be the same. For example, in your code, if a.variable has trailing whitespace, you would not see this in the output and yet the strings would also not be equal.
Try writing both strings surrounded by some characters. I suspect that you will see there is some extra whitespace somewhere:
std::cout << '[' << a.variable << ']' << std::endl;
std::cout << '[' << "string" << ']' << std::endl;
Consider also displaying a.variable.size(). If it's not 6, then the two strings cannot be equal since they have different lengths.
For the purposes of typeid, a.variable is of type std::string while the string literal "string" is of type char const [7].
That explains the output of
std::cout << typeid(a.variable).name() << std::endl;
std::cout << typeid("string").name() << std::endl;
Confused about the output for the second code snippet. Why is the output different than the first program?
#include <iostream>
using namespace std;
int main() {
int s[5] = {1, 2 , 3, 4, 5};
int *p = s;
int first = *(p++);
int second = *++p;
int third = ++*p;
int fourth = *p++;
cout << "*p++ is " << first << endl
<< "*++p is " << second << endl
<< "++*p is " << third << endl
<< "*p++ is " << fourth << endl;
return 0;
}
output:
*p++ is 1
*++p is 3
++*p is 4
*p++ is 4
https://ideone.com/Qu2uIJ
I expected the output would be the same in the code below:
#include <iostream>
using namespace std;
int main() {
int s[5] = {1, 2 , 3, 4, 5};
int *p = s;
cout << "*p++ is " << *p++ << endl
<< "*++p is " << *++p << endl
<< "++*p is " << ++*p << endl
<< "*p++ is " << *p++ << endl;
return 0;
}
output:
*p++ is 3
*++p is 3
++*p is 3
*p++ is 1
https://ideone.com/nwd7xR
What's going on?
Your statement cout << "*p++ is " << *p++ << endl << ...; is treated as one expression, and C++ is almost free in the order of evaluating the arguments used in expressions. SO it is undefined (behaviour actually) in which order the p++ and ++-statements are evaluated.
In the first approach, evaluation order is according to the variables to which you assign. In the second, C++ is free (and treats it as UB if there is no sequence point in the expression; in your's, there isn't a sequence point).
As per operator precedence, operator << is left to right which occurs in cout object in sequence one after the other and sequence of evaluation of arguments to operator << is unspecified.
Between consecutive "sequence points" an object's value can be
modified only once by an expression.
https://msdn.microsoft.com/en-us/library/azk8zbxd.aspx
The second code snippet attempts to modify the pointer's value multiple times within one sequence.
List of C Sequence Points:
Left operand of the logical-AND operator (&&).
Left operand of the logical-OR operator (||).
Left operand of the comma operator (,)
Function-call operator ()
First operand of the conditional operator aka ternary operator ( ? : )
The end of a full initialization expression (that is, an expression
that is not part of another expression such as the end of an
initialization in a declaration statement).
The expression in an expression statement. Expression statements
consist of an optional expression followed by a semicolon (;). The
expression is evaluated for its side effects and there is a sequence
point following this evaluation.
The controlling expression in a selection (if or switch) statement.
The controlling expression of a while or do statement.
Each of the three expressions of a for statement.
The expression in a return statement.
I am learning C++ and just started reading "Programming Principles and Practice" by Bjarne Stroustrup and he uses this code to illustrate a point:
#include "std_lib_facilities.h"
using namespace std;
int main() // C++ programs start by executing the function main
{
char c = 'x';
int i1 = c;
int i2 = 'x';
char c2 = i1;
cout << c << ' << i1 << ' << c2 << '\n';
return 0;
}
I am familiar in general with the difference between double and single quotes in the C++ world, but would someone kindly explain the construction and purpose of the section ' << i1 << '
Thanks
cout << c << ' << i1 << ' << c2 << '\n';
appears to be a typo in the book. I see it in Programming Principles and Practice Using C++ (Second Edition) Second printing. I do not see it listed in the errata.
According to the book, the intended output is
x 120 x
But what happens here is ' << i1 << ' attempts to compress the << i1 << to a multi-byte character and prints out an integer (most likely 540818464-> 0x203C3C20 -> ASCII values of ' ', '<', '<', ' ') because cout doesn't know wide characters. You'd need wcout for that. End result is output something like
x540818464x
and a warning or two from the compiler because while it's valid C++ code, it's almost certainly not what you want to be doing.
The line should most likely read
cout << c << ' ' << i1 << ' ' << c2 << '\n';
which will output the expected x 120 x
In other words, Linker3000, you are not crazy and not misunderstanding the example code.
Anyone know who I should contact to log errata or get a clarification on the off chance there is some top secret sneakiness going way over my head?
Before answering your question, here is a little background on what that is actually doing. Also note that there is a typo in the example, the string constant should have been double quoted:
cout << c << " << i1 << " << c2 << "\n";
In C++, operators can be overloaded so that they mean different things with different functions. In the case of cout, the << operator is overloaded as the "Insertion Operator". Think of it as taking the operand on the right, and inserting it (or sending it) into the operator on the left.
For example,
cout << "Hello World";
This takes the string "Hello World", and sends it to cout for processing.
So what beginners do not get is what something like this means:
cout << "Hello" << " World";
This is doing the same thing, but the operator precedence says to perform the injections from left to right. To make this work, the cout object returns itself as a function return value. Why is this important? Because the above statement is actually two separate operator evaluations:
(cout << "Hello") << " World";
This first injects "Hello" to cout, which outputs it, then continues to evaluate the next inject operator. Because cout returns itself, after the (cout << "Hello") is executed you have the following still to be evaluated:
cout << " World";
This expression injects " World" into the cout object, which then outputs " World", with the net effect being that you see "Hello World" just like the first time.
So in your example, what is it doing?
cout << c << " << i1 << " << c2 << "\n";
This is evaluated left to right as follows:
((((cout << c) << " << i1 << ") << c2) << "\n"); => Outputs value of c
((((cout ) << " << i1 << ") << c2) << "\n"); => Outputs string " << i1 << "
((( cout ) << c2) << "\n"); => Outputs value of c2
(( cout ) << "\n"); => Outputs newline character
( cout ); => No more output
Expression completes and returns the cout object as the expression value.
Assuming c='x' and c2='x', the final output from this expression is the following character string output on a single line:
x << i1 << x
For beginners, all those insertion operators << look a little strange. It is because you are dealing with objects. You could build the string up as a complete formatted object before injecting it into cout, and while that make the cout expression look simpler, we do not do that in C++ because it makes your code more complex and error prone. Note also, there is nothing special about the cout object. If you wanted to output to the standard error stream, you would use cerr instead. If you wanted to output to a file, your would instantiate a stream object that outputs to the desired file. That rest of the code in your example would be the same.
In C, the same thing would be done procedurally using a format string:
printf("%d << i1 << %d\n", i1, c2);
This is allowed in C++ too, because C++ is a superset of C. Many C++ programmers still use this output method, but that is because those programmers learned C first, and may not have fully embraced the object oriented nature of C++
Note that you may also have seen the << operator in the context of mathematical expressions like:
A = A << 8;
In this case, the << operator is the bitwise rotate operation. It has nothing to do with output to cout. It will rotate the bits in A to the left by eight bits.
When I print the id of a stream in a single expression it prints it backwards. Normally this is what comes out:
std::stringstream ss;
std::cout << ss.xalloc() << '\n';
std::cout << ss.xalloc() << '\n';
std::cout << ss.xalloc();
Output is:
4
5
6
But when I do it in one expression it prints backwards, why?
std::stringstream ss;
std::cout << ss.xalloc() << '\n'
<< ss.xalloc() << '\n'
<< ss.xalloc();
Output:
6
5
4
I know the order of evaluation is unspecified but then why does the following always result in the correct order:
std::cout << 4 << 5 << 6;
Can someone explain why xalloc behaves differently? Thanks.
This isn't related to xalloc; any other function that returns a different value each time it's called would do the same thing. The order of evaluation of the arguments is unspecified; the compiler can make the three function calls in any order. Once all the arguments have been evaluated, the order of insertion is from left to right.
I use the stream operator << and the bit shifting operator << in one line.
I am a bit confused, why does code A) not produce the same output than code B)?
A)
int i = 4;
std::cout << i << " " << (i << 1) << std::endl; //4 8
B)
myint m = 4;
std::cout << m << " " << (m << 1) << std::endl; //8 8
class myint:
class myint {
int i;
public:
myint(int ii) {
i = ii;
}
inline myint operator <<(int n){
i = i << n;
return *this;
}
inline operator int(){
return i;
}
};
thanks in advance
Oops
Your second example is undefined behavior.
You have defined the << operator on your myint class as if it were actually <<=. When you execute i << 1, the value in i is not modified, but when you execute m << 1, the value in m is modified.
In C++, it is undefined behavior to both read and write (or write more than once) to a variable without an intervening sequence point, which function calls and operators are not, with respect to their arguments. It is nondeterministic whether the code
std::cout << m << " " << (m << 1) << std::endl;
will output the first m before or after m is updated by m << 1. In fact, your code may do something totally bizarre, or crash. Undefined behavior can lead to literally anything, so avoid it.
One of the proper ways to define the << operator for myint is:
myint operator<< (int n) const
{
return myint(this->i << n);
}
(the this-> is not strictly necessary, just my style when I overload operators)
Because int << X returns a new int. myint << X modifies the current myint. Your myint << operator should be fixed to do the former.
The reason you're getting 8 for the first is that apparently m << 1 is called first in your implementation. The implementation is free to do them in any order.
Your << operator is in fact a <<= operator. If you replace the line with
std::cout << i << " " << (i <<= 1) << std::endl; //8 8
you should get 8 8.
since m is a myInt your second example could be rewritten as:
std::cout << m << " " << (m.operator<<( 1)) << std::endl;
The order of evaluation for the subexpressions m and (m.operator<<( 1)) is unspecified, so there's no saying which "m" you'll get for the 1'st expression that m is used in (which is a simple m expression). So you might get a result of "4 8" or you might get "8 8".
Note that the statement doesn't result in undefined behavior because there are sequence points (at least one function call) between when m is modified and when it's 'read'. But the order of evaluation of the subexpressions is unspecified, so while the compiler has to produce a result (it can't crash - at least not legitimately), there's no saying which of the two possible results it should produce.
So the statement is about as useful as one that has undefined behavior, which is to say it's not very useful.
Well (m << 1) is evaluated before m and therefore m holds 8 already, as in your operator<< you overwrite your own value.
This is wrong behaviour on your side, the operator<< should be const and not change your object.
Because the << operator of myint modifies its lhs. So after evaluating m << 1, m will actually have the value 8 (while i << 1 only returns 8, but does not make i equal to 8). Since it is not specified whether m<<1 executes before cout << m (because it's not specified in which order the arguments of a function or operator are evaluated), it is not specified whether the output will be 8 8 or 4 8.
The C++ language does not define the order of evaluation of operators. It only defines their associativity.
Since your results depend on when the operator<< function is evaluated within the expression, the results are undefined.
Algebraic operator $ functions should always be const and return a new object:
inline myint operator <<(int n) const { // ensure that "this" doesn't change
return i << n; // implicit conversion: call myint::myint(int)
}