You are here:

C++/Question in C++ using for! HELP

Advertisement


Question
The Question is Write a program that output the numbers 0 to 8 in three columns, where the width of each of them 3. The output should be as follows:
0  1  2
3  4  5
6  7  8




so what i've done so far is :


#include<iostream.h>
void main()
{
int x;
for (x=0;x<=8;x++)
cout<<x<<"   "<<x++<<"   "<<x++<<"
"<<endl;
}


my problem is that my output is the oppisite like the following :
2  1  0
5  4  3
8  7  6

help me please

Answer
Firstly, in general using pre or post increment or decrement (++x, x++, --x, x--) in (complex) expressions can be dangerous as you never know when the compiler will execute that part of the expression (a sub-expression) - so results can be unpredictable.

That is if your expression is complex enough that the compiler can (will) split it into sub-expressions then the compiler is free to evaluate these sub-expressions in any order.

In fact certain such uses are marked as having unspecified behaviour by the C++ language specification - although it is not written in an easy to figure way. Here is one example from the C++ standard (Section 5 paragraph 4):

       i = ++i + 1; // the behavior is unspecified

Two particular restrictions are placed on expressions, and breaking these rules results in undefined behaviour:

   1/ "a scalar object shall have its stored value modified at most once"
   2/ "the prior value shall be accessed only to determine the value to be stored"

(Scalar objects are single items like a single int object).

These conditions have to hold between specific points in the code. These points are called sequence points in the C++ standard; they  are described thus:

   "At certain specified points in the execution sequence called sequence points,
    all side effects of previous evaluations shall be complete and no side effects
    of subsequent evaluations shall have taken place"

A side effect is defined as:

   "Accessing an object designated by a volatile, modifying an object, calling a
    library I/O function, or calling a function that does any of those operations
    are all side effects, which are changes in the state of the execution environment"

It is noted that:

   "Evaluation of an expression might produce side effects."
   
So evaluating expressions may well cause side effects as values may be modified and/or library I/O functions called etc. Further, there are restrictions on what is allowed between two expression evaluating sequence points in the code. However at these points all such side effects will have completed or not begun. So the next question is where do these sequence points occur?

Well first off there is a sequence point at the completion of evaluation of each full expression.
   
And of particular interest here, when calling a function there are sequence points:
   
   - after the evaluation of all function arguments (if any) which takes place before execution of any
     expressions or statements in the function body.
   
   - after the copying of a returned value and before the execution of any expressions outside the function.
   
Also pertinent to this question is the observation in the C++ standard that:

   "Several contexts in C++ cause evaluation of a function call, even though no
    corresponding function call syntax appears" (in the code).

And that:
    
   "The sequence points at function entry and function exit  (as described above) are
    features of the function calls as evaluated, whatever the syntax of the expression
    that calls the function might be."

So, the sequence points pertaining to function calls apply even when the function calls are implicit and hidden by C++ syntax.

It is this point that applies here. Although you seem not to call any functions you are. The use of operator << with output stream (std::ostream) types makes use of operator overloading - that is the use of the << operator is overloaded by having a function supplied for the types used in the operation - in this case a std::ostream (or derivative) object and an int object.

Operator overload functions for the << operator (called operator<<) are usually implemented as stand alone functions that are not class members. For the built in arithmetic types such as int this is different. They are implemented are part of the std::ostream class. Hence your use of << to output to (std::) cout is equivalent to writing:

       std::cout.operator<<(x).operator<<(x++).operator<<(x++);

Note that for simplicity I have left out the calls to the operator<< functions for char const * (for outputting the string literals) and std::endl (for writing a newline to the stream and flushing the ostream object).

You can in fact use the above statement in your code if you wish to try it out - due to the lack of spacing the output will be:

   210543876

OK so how do we use this transformation to work out what is going on.

Well first each of the uses of operator<< above represents one call to the std::ostream::operator<< member function. Each of these takes an integer as a parameter and returns a reference to the std::ostream object.

In fact there is even more syntactic sugar going on. Calling a member function using class member access syntax could just as well be represented by a call to the member function with the object it is called for being passed as the first parameter:

  std::cout.operator<<(x) => operator<<(std::cout, x)

Although this is not valid C++ syntax underneath it can be considered as what goes on (although a C++ implementation is free do things differently if it wished to and it worked, most if not all work similarly to the above).

Hence we can consider the sequence of calls to member operator<< functions to be equivalent to:

       operator<<( operator<<( operator<<(std::cout, x), x++ ), x++ );

Now at last we have the sequence of output operations in a form I can help explain what is going on (phew!)

Checking what I said about sequence points we see that there will be sequence points before each set of function call arguments is passed to their functions, and after each call returns.

The outer (1st) call has parameters:

   operator<<( operator<<(std::cout, x), x++ )

and

   x++

These are evaluated. When evaluation is complete there is a sequence point - all side effects (modifications to data and I/O function calls) will be complete. Only after this point is the function call made.

Remember that the compiler is free to evaluate these arguments in any order.

So let us assume this is the first time around the for loop so x starts off as 0, and that the compiler chooses to evaluate the arguments last one first.

Hence x++ is evaluated first:

   The current value of x, 0, is used for the argument value to the outer operator<< function call.
   x is incremented x -> 1.
  
Next operator<<( operator<<(std::cout, x), x++ ) is evaluated.
 
This means operator<<(std::cout, x) and x++ have to be evaluated
As before x++ is evaluated first:

   The current value of x, 1, is used for the argument value to the middle operator<< function call.
   x is incremented x -> 2.
   
Next operator<<(std::cout, x) is evaluated.
Again x is evaluated first:
   
   The current value of x, 2, is used for the argument value to the inner operator<< function call.

Next std::cout is evaluated:

   std::cout is used as the argument to the inner call to operator<<
   
The inner call executes with parameter values reference to std::cout and 2; 2 is output and std::cout is returned (by reference)

The returned value from the inner call to operator<<, the result of the call to operator<<(std::cout, x), is passed to the middle call to operator<<.

The middle call executes with parameter values reference to std::cout and 1; 1 is output and std::cout is returned (by reference)

The returned value from the middle call to operator<<, the value of the call to operator<<( operator<<(std::cout, x), x++ ), is passed to the outer call to operator<<.

The outer call executes with parameter values reference to std::cout and 0; 0 is output and std::cout is returned (by reference)

So we have the values:

   2 1 0

Output in that order.

Of course the compiler could have chosen to evaluate the arguments to operator<< in the other order. In this case we would have got:

operator<<( operator<<(std::cout, x), x++ ) is evaluated first. The parameters to this call will be evaluated.

Thus operator<<(std::cout, x) will be evaluated

   std::cout is used as the argument to the inner call to operator<<
   The current value of x, 0, is used for the argument value to the inner operator<< function call.

The inner call executes with parameter values reference to std::cout and 0; 0 is output and std::cout is returned (by reference)

   The returned value of reference to std::cout is used as the first parameter to the middle call to operator<<

Next the x++ parameter to the middle call to operator<< is evaluated

   The current value of x, 0, is used for the argument value to the middle operator<< function call.
   x is incremented x -> 1.

The middle call executes with parameter values reference to std::cout and 0; 0 is output and std::cout is returned (by reference)

   The returned value of reference to std::cout is used as the first parameter to the outer call to operator<<

Next the ++x argument to the outer call to operator<< is evaluated

   The current value of x, 1, is used for the argument value to the middle operator<< function call.
   x is incremented x -> 2.

The outer call executes with parameter values reference to std::cout and 1; 1 is output and std::cout is returned (by reference)

So the output in this case would be:

   0 0 1

Still not correct.

I tried your code with two very different compilers (Microsoft Visual C++ 2008 and GNU g++ 4.2.4) and _both_ chose to do what your compiler did. Both produced a program having the same output as you show. One explanation for this could be that C and C++ have to push their function arguments on the stack in reverse order for technical reasons to do with support for functions with variable number of arguments. Hence if you are to set up the last argument for a function call first it seems natural to evaluate it first.

So in short, you have to be careful using ++ and -- in complex expressions not to get not only undefined or unspecified behaviour but also to get into a mess in the first place!

I suggest you consider the use of the % (modulus, or remainder, operator) and an if / else within the loop and only output one value each time around the for loop. [hint: x%3==2 will be true if x is 2, 5 or 8].

Oh, other things I note are that:

1/ you are using an old pre-standard (the ISO C++ standard was released in 1998) header file <iostream.h>.
Unless you are using a really ancient compiler the standard header is just <iostream>. You will then have to add std:: to cout and endl: std::cout, std::endl.

2/ The declaration of main is non-standard (an old Microsoft compiler?). The standard form of main which accepts no command line argument parameters is:

   int main();

However if you are using an old Microsoft compiler (version 6 or earlier I think) then you will require a:

   return 0;

before main ends.

The code posted has no indentation and is illegal. This may be the result of posting through AllExperts. The line:

   cout<<x<<" "<<x++<<" "<<x++<<"    "<<endl;

was split across 2 lines for some reason:

   cout<<x<<" "<<x++<<" "<<x++<<"
   "<<endl;

Which leaves a dangling open string literal on BOTH lines, which is not legal.

4/ You could have added a bit more space around items - the code is very cramped.

5/ For C++ it is more idiomatic to prefer pre-increment: ++x to post increment: x++ in cases where it does not matter and either will do. It is not a problem here using int but user defined types can define their own increment and decrement operators and the post forms are generally defined in terms of the pre forms and as a result tend to be less efficient. So we like to use ++x and the like just to be in the habit of doing it, even if there is no performance hit.
 
Below is how I would format/modify your code for standard C++:

       #include <iostream>

       int main()
       {
         int x;
         for (x=0; x<=8; ++x)
         std::cout << x << "  " << x++ << "   " << x++ << "     " << std::endl;

         return 0;  // Only required for non-compliant compilers.
       }

In fact I would make it longer and add  { } around the currently single for-loop clause statement:

       #include <iostream>

       int main()
       {
         int x;
         for (x=0; x<=8; ++x)
         {
         std::cout << x << "  " << x++ << "   " << x++ << "     " << std::endl;
         }

         return 0;  // Only required for non-compliant compilers.
       }

The reason for this is that it is quite common to add more lines within such clauses and then you _need_ the braces so I put them in to start with - at least in 99.9999% of cases. This is a very personal thing however.

I would also move the definition of x into the for loop statement:

        #include <iostream>

        int main()
        {
         for (int x=0; x<=8; ++x)
         {
         std::cout << x << "  " << x++ << "   " << x++ << "     " << std::endl;
         }

         return 0;  // Only required for non-compliant compilers.
        }
 
But if your compiler is old it may not support this syntax.

Note that if you are using an old Microsoft compiler then you can obtain a copy of an express edition of the latest 2008 version for free (other than having to download a very large file or two). See http://www.microsoft.com/express/vc/ for starters.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.