Use Informix Object Interface for C++ for stored procedures/functions with out parameters - c++

It's simple - is there a way to use this lib to call stored procedure or function, that returns more than one result? I know about the ITRoutingManager, but it seems to return just one value..
In details, here's what I mean:
CREATE FUNCTION test_out1( pin INT )
RETURNING INT;
DEFINE param INT;
LET param = 321;
RETURN param;
END FUNCTION;
Returns 321, I can get the value with ITValue and ITConversions. So this is fine. But the following is not:
CREATE FUNCTION test_out2( pin INT )
RETURNING INT, INT;
DEFINE param INT;
LET param = 321;
DEFINE param2 INT;
LET param2 = 123;
RETURN param, param2;
END FUNCTION;
When I do routine.GetRoutine( "function test_out2( int )" ), it's bound fine, so no problem with that. But see this:
std::cout &lt&lt "Result type: " &lt&lt routine.ResultType()->Name() IsRow() ? "row, " : ", " )
&lt&lt (routine.ResultType()->IsCollection() ? "collection, " : ", " )
&lt&lt routine.ResultType()->Quality() &lt&lt "\n\n";
prints integer, , , null, note the integer.. Why is integer, not row, for example. And how to get the 2 values, returned by the function? Another interesting fact - the returned value is 0(when I convert it to int, using the ITConversions class), not 123, nor 321..
There have to be a way. This is a special library, written for Informix servers, by Informix developers and it would be strange, if this is not possible.
The same for functions, but I guess it's the same there.
NOTE: there's no such thing as out parameters in the common case, for informix procedures/functions (Informix: procedure with output parameters?)

As you note, Informix does not have 'OUT' parameters really; it returns values.
In regular ESQL/C, you treat a list of output values symmetrically with a list of input values; I would expect to do the same with this code, therefore. Whatever technique you use to pass 2 arguments to the function is likely - but by no means guaranteed - to be how you get multiple returned values.
In case of doubt, treat it as you would treat a SELECT statement that returns multiple rows. That is, do the analogues of:
PREPARE s FROM "EXECUTE PROCEDURE test_out2(?)";
DECLARE c CURSOR FOR s;
OPEN c USING :input_value;
while (sqlca.sqlcode == 0)
{
FETCH c INTO :out_value1, :out_value2;
if (sqlca.sqlcode != 0)
break;
...use values...
}
CLOSE c;
FREE c;
FREE s;
I would recommend using ODBC over OIC++. The OIC++ interface is built on top of another library, DMI, which in turn is built on top of another library that accesses the DBMS - I forget whether it is ESQL/C or ODBC based, or one of the core libraries those are built on. Using unixODBC as your driver manager and an appropriate ODBC driver makes more sense to me than using OIC++.
I've no real idea how that looks in OIC++; I've never used it, but only done some cursory maintenance of it.
On the whole, you would be best advised not to use OIC++ for new work. Informix continues to distribute it for backwards compatibility rather than to encourage new use.

Related

change pointer of char[] in c++

I had to write a program that declares char text[16]; and int number; and then fills it with input from the user. Then I have to call another function (without passing anything) and recall that data from the stack and display it.
I was able to find both of them
// This is the function that is called without passing any variables
int number;
char text[16];
cout << *(&text + 5) << endl; // This outputs the correct text but I can not figure out how to assign it to text
number = *(int*)(&number + 20); // This works and outputs the correct number and saves correctly to int number;
cout << "\tnumber: "
<< number
<< endl;
cout << "\ttext: "
<< text
<< endl;
I would like to know if there is a way to transfer the text from *(&text + 5) to char text[16];
What you are doing is going to result in undefined behavior. Depending heavily on the compiler and therefore in turn on the architecture. The proof being that when I compile and run your code with different optimization flags I get different results. Check out https://en.wikipedia.org/wiki/Buffer_overflow
The first expression *(&text + 5) evaluates to taking the address of the text pointer in memory, adding 5 to it and then dereferencing that to get a character value that is stored at that location. This can be pretty much anything on the stack at that time.
&number + 20 will definitely go off the "visible" stack, this is pointer arithmetic and will result in you adding 20*sizeof(int) to the pointer to the memory address of number on the stack.
If this is what you are intending to do then you should probably use strcpy as suggested by #JafferWilson
From reading the comments on the answer by Curious the answer is:
There is no proper way to read local variables in another function in C++ without passing them (or pointers to them or references to them) as parameters (or within objects you pass as parameters).
You can assign file scope (so called global) variables and read them in other functions. That is almost always a bad idea.
I get the feeling you might be coming from an assembler programming background to even try this sort of thing. You need to surrender a bit more to the structured programming paradigm.

How to calculate the cumulative density function of a sum of random variables in C++? [duplicate]

I would like to, within my own compiled C++ code, check to see if a library package is loaded in R (if not, load it), call a function from that library and get the results back to in my C++ code.
Could someone point me in the right direction? There seems to be a plethora of info on R and different ways of calling R from C++ and vis versa, but I have not come across exactly what I am wanting to do.
Thanks.
Dirk's probably right that RInside makes life easier. But for the die-hards... The essence comes from Writing R Extensions sections 8.1 and 8.2, and from the examples distributed with R. The material below covers constructing and evaluating the call; dealing with the return value is a different (and in some sense easier) topic.
Setup
Let's suppose a Linux / Mac platform. The first thing is that R must have been compiled to allow linking, either to a shared or static R library. I work with an svn copy of R's source, in the directory ~/src/R-devel. I switch to some other directory, call it ~/bin/R-devel, and then
~/src/R-devel/configure --enable-R-shlib
make -j
this generates ~/bin/R-devel/lib/libR.so; perhaps whatever distribution you're using already has this? The -j flag runs make in parallel, which greatly speeds the build.
Examples for embedding are in ~/src/R-devel/tests/Embedding, and they can be made with cd ~/bin/R-devel/tests/Embedding && make. Obviously, the source code for these examples is extremely instructive.
Code
To illustrate, create a file embed.cpp. Start by including the header that defines R data structures, and the R embedding interface; these are located in bin/R-devel/include, and serve as the primary documentation. We also have a prototype for the function that will do all the work
#include <Rembedded.h>
#include <Rdefines.h>
static void doSplinesExample();
The work flow is to start R, do the work, and end R:
int
main(int argc, char *argv[])
{
Rf_initEmbeddedR(argc, argv);
doSplinesExample();
Rf_endEmbeddedR(0);
return 0;
}
The examples under Embedding include one that calls library(splines), sets a named option, then runs a function example("ns"). Here's the routine that does this
static void
doSplinesExample()
{
SEXP e, result;
int errorOccurred;
// create and evaluate 'library(splines)'
PROTECT(e = lang2(install("library"), mkString("splines")));
R_tryEval(e, R_GlobalEnv, &errorOccurred);
if (errorOccurred) {
// handle error
}
UNPROTECT(1);
// 'options(FALSE)' ...
PROTECT(e = lang2(install("options"), ScalarLogical(0)));
// ... modified to 'options(example.ask=FALSE)' (this is obscure)
SET_TAG(CDR(e), install("example.ask"));
R_tryEval(e, R_GlobalEnv, NULL);
UNPROTECT(1);
// 'example("ns")'
PROTECT(e = lang2(install("example"), mkString("ns")));
R_tryEval(e, R_GlobalEnv, &errorOccurred);
UNPROTECT(1);
}
Compile and run
We're now ready to put everything together. The compiler needs to know where the headers and libraries are
g++ -I/home/user/bin/R-devel/include -L/home/user/bin/R-devel/lib -lR embed.cpp
The compiled application needs to be run in the correct environment, e.g., with R_HOME set correctly; this can be arranged easily (obviously a deployed app would want to take a more extensive approach) with
R CMD ./a.out
Depending on your ambitions, some parts of section 8 of Writing R Extensions are not relevant, e.g., callbacks are needed to implement a GUI on top of R, but not to evaluate simple code chunks.
Some detail
Running through that in a bit of detail... An SEXP (S-expression) is a data structure fundamental to R's representation of basic types (integer, logical, language calls, etc.). The line
PROTECT(e = lang2(install("library"), mkString("splines")));
makes a symbol library and a string "splines", and places them into a language construct consisting of two elements. This constructs an unevaluated language object, approximately equivalent to quote(library("splines")) in R. lang2 returns an SEXP that has been allocated from R's memory pool, and it needs to be PROTECTed from garbage collection. PROTECT adds the address pointed to by e to a protection stack, when the memory no longer needs to be protected, the address is popped from the stack (with UNPROTECT(1), a few lines down). The line
R_tryEval(e, R_GlobalEnv, &errorOccurred);
tries to evaluate e in R's global environment. errorOccurred is set to non-0 if an error occurs. R_tryEval returns an SEXP representing the result of the function, but we ignore it here. Because we no longer need the memory allocated to store library("splines"), we tell R that it is no longer PROTECT'ed.
The next chunk of code is similar, evaluating options(example.ask=FALSE), but the construction of the call is more complicated. The S-expression created by lang2 is a pair list, conceptually with a node, a left pointer (CAR) and a right pointer (CDR). The left pointer of e points to the symbol options. The right pointer of e points to another node in the pair list, whose left pointer is FALSE (the right pointer is R_NilValue, indicating the end of the language expression). Each node of a pair list can have a TAG, the meaning of which depends on the role played by the node. Here we attach an argument name.
SET_TAG(CDR(e), install("example.ask"));
The next line evaluates the expression that we have constructed (options(example.ask=FALSE)), using NULL to indicate that we'll ignore the success or failure of the function's evaluation. A different way of constructing and evaluating this call is illustrated in R-devel/tests/Embedding/RParseEval.c, adapted here as
PROTECT(tmp = mkString("options(example.ask=FALSE)"));
PROTECT(e = R_ParseVector(tmp, 1, &status, R_NilValue));
R_tryEval(VECTOR_ELT(e, 0), R_GlobalEnv, NULL);
UNPROTECT(2);
but this doesn't seem like a good strategy in general, as it mixes R and C code and does not allow computed arguments to be used in R functions. Instead write and manage R code in R (e.g., creating a package with functions that perform complicated series of R manipulations) that your C code uses.
The final block of code above constructs and evaluates example("ns"). Rf_tryEval returns the result of the function call, so
SEXP result;
PROTECT(result = Rf_tryEval(e, R_GlobalEnv, &errorOccurred));
// ...
UNPROTECT(1);
would capture that for subsequent processing.
There is Rcpp which allows you to easily extend R with C++ code, and also have that C++ code call back to R. There are examples included in the package which show that.
But maybe what you really want is to keep your C++ program (i.e. you own main()) and call out to R? That can be done most easily with
RInside which allows you to very easily embed R inside your C++ application---and the test for library, load if needed and function call are then extremely easy to do, and the (more than a dozen) included examples show you how to. And Rcpp still helps you to get results back and forth.
Edit: As Martin was kind enough to show things the official way I cannot help and contrast it with one of the examples shipping with RInside. It is something I once wrote quickly to help someone who had asked on r-help about how to load (a portfolio optimisation) library and use it. It meets your requirements: load a library, accesses some data in pass a weights vector down from C++ to R, deploy R and get the result back.
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
//
// Simple example for the repeated r-devel mails by Abhijit Bera
//
// Copyright (C) 2009 Dirk Eddelbuettel
// Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois
#include <RInside.h> // for the embedded R via RInside
int main(int argc, char *argv[]) {
try {
RInside R(argc, argv); // create an embedded R instance
std::string txt = "suppressMessages(library(fPortfolio))";
R.parseEvalQ(txt); // load library, no return value
txt = "M <- as.matrix(SWX.RET); print(head(M)); M";
// assign mat. M to NumericMatrix
Rcpp::NumericMatrix M = R.parseEval(txt);
std::cout << "M has "
<< M.nrow() << " rows and "
<< M.ncol() << " cols" << std::endl;
txt = "colnames(M)"; // assign columns names of M to ans and
// into string vector cnames
Rcpp::CharacterVector cnames = R.parseEval(txt);
for (int i=0; i<M.ncol(); i++) {
std::cout << "Column " << cnames[i]
<< " in row 42 has " << M(42,i) << std::endl;
}
} catch(std::exception& ex) {
std::cerr << "Exception caught: " << ex.what() << std::endl;
} catch(...) {
std::cerr << "Unknown exception caught" << std::endl;
}
exit(0);
}
This rinside_sample2.cpp, and there are lots more examples in the package. To build it, you just say 'make rinside_sample2' as the supplied Makefile is set up to find R, Rcpp and RInside.

Easier-to-type alternative to std::cout for printing to screen in C++

Often I just want to quickly check the contents of a series of variables (let's call them a,b,c,d and e, and suppose they're a mixture of floats, integers and strings). I'm fed up typing
cout << a << " " << b << " " << " " << c << " " << " " << d << " " << e << endl;
Is there a more convenient (less key-strokes) way to quickly dump a few variables to stdout in C++? Or do C++ people just always define their own simple print function or something? Obviously something like
printf("%d %f %s %d %s\n",a,b,c,d,e);
is not the alternative I'm looking for, but rather something like
print a,b,c,d,e
Even
print*, a,b,c,d,e
or
write(*,*) a,b,c,d,e
isn't too inconvenient to type.
Of course, googling 'quickly print to screen in C++' keeps just sending me back to std::cout.
Is it that, what you want?
print(a, b, c);
That would be this.
template <typename T>
void print(T t)
{
std::cout << t << " ";
}
template<typename T, typename... Args>
void print(T t, Args... args)
{
std::cout << t << " ";
print(args...) ;
}
It's easy to create a "print" class which have an overloaded template operator,, then you could do something like
print(),a,b,c,d;
The expression print() would create a temporary instance of the print class, and then use that temporary instance for the printing with the comma operator. The temporary instance would be destroyed at the end of the expression (after last comma overload is called).
The implementation could look something like this:
struct print
{
template<typename T>
print& operator,(const T& v)
{
std::cout << v;
return *this;
}
};
Note: This is just off my head, without any testing.
Is there a more convenient (less key-strokes) way to quickly dump a
few variables to stdout in C++?
I would have to say No, not in the language. But I do not consider std::cout a challenging amount to type.
You can tryout the template methods provided by other answer's.
But you should try GDB (or some debugger available on your system). GDB can 'dump' automatic variables with no _effort_ at all, as automatic var's for the current stack frame are always kept up-to-date in the "Locals" window.
Or do C++ people just always define their own simple print function or something?
No, or maybe something.
I use std::cout and std::cerr (as defined) for lots of debugging, but not in the 'how can I save the most typing' frame of mind.
My view is that creating a 'convenience' (i.e. not required) function is appropriate for doing something you wish to repeat. My rule of thumb is 3 times ... if I do a particular something 3 (or more) times (like generate a std::cout statement with the same or similar variables in it) then I might write a function (rather than copy the line) for that repeated effort.
Typically, I use one of two (what I call) disposable debug methods ... and most of my objects also have both show() and dump(), and there can be multiple show/dump functions or methods, each with different signatures, and default values.
if(dbg1) show(a,b,c,d,e);
if(dbg1b) show(b);
// etc
and
if(dbg2) dump(a,b,c,d,e);
Show typically uses and does what what std::cout provides, and little else.
Dump does what show does, but also might provide an alternate view of the data, either hex or binary translations of the values, or perhaps tables. What ever helps.
Disposable does not mean I will dispose of them, but rather I might, and I often get tired of output that does not change, so I set dbgX to false when this code seems to be working, at least until I decide to dispose of the debug invocation.
But then, you do have to implement each of the functions and methods, and yes, you are going to have to learn to type.
If these variables are automatic, you should know that the debugger GDB automatically displays them in a window called "Locals", and keeps them up-to-date during single step.
In GDB, object instance contents can often be displayed with "p *obj", and there are ways to add a particular obj name to the local display window.
It does not take a lot to run GDB. If you object to creating the 80 char std::cout code above, it takes far less typing to launch GDB, set break in main, and run the simple task under gdb control, (then single step to observe these variables at any step in your code) not just where you happened to insert a show() or dump() command.
And if you have GDB, you can also command to print using "p show()" (when the show() function is in scope) to see what the in-scope variables look like to std::cout (if you don't believe the "Locals" window).
GDB allows you to "p this->show()" when stepping through a method of the instance, or "p myObj->show()" when the myObj is accessible.
ALso, "p *this" and "p *myObj" will provide a default, typically useful, display of the current contents your object.
Anyway. Yes you can always work hard to shorten your typing effort.

Calling R Function from C++

I would like to, within my own compiled C++ code, check to see if a library package is loaded in R (if not, load it), call a function from that library and get the results back to in my C++ code.
Could someone point me in the right direction? There seems to be a plethora of info on R and different ways of calling R from C++ and vis versa, but I have not come across exactly what I am wanting to do.
Thanks.
Dirk's probably right that RInside makes life easier. But for the die-hards... The essence comes from Writing R Extensions sections 8.1 and 8.2, and from the examples distributed with R. The material below covers constructing and evaluating the call; dealing with the return value is a different (and in some sense easier) topic.
Setup
Let's suppose a Linux / Mac platform. The first thing is that R must have been compiled to allow linking, either to a shared or static R library. I work with an svn copy of R's source, in the directory ~/src/R-devel. I switch to some other directory, call it ~/bin/R-devel, and then
~/src/R-devel/configure --enable-R-shlib
make -j
this generates ~/bin/R-devel/lib/libR.so; perhaps whatever distribution you're using already has this? The -j flag runs make in parallel, which greatly speeds the build.
Examples for embedding are in ~/src/R-devel/tests/Embedding, and they can be made with cd ~/bin/R-devel/tests/Embedding && make. Obviously, the source code for these examples is extremely instructive.
Code
To illustrate, create a file embed.cpp. Start by including the header that defines R data structures, and the R embedding interface; these are located in bin/R-devel/include, and serve as the primary documentation. We also have a prototype for the function that will do all the work
#include <Rembedded.h>
#include <Rdefines.h>
static void doSplinesExample();
The work flow is to start R, do the work, and end R:
int
main(int argc, char *argv[])
{
Rf_initEmbeddedR(argc, argv);
doSplinesExample();
Rf_endEmbeddedR(0);
return 0;
}
The examples under Embedding include one that calls library(splines), sets a named option, then runs a function example("ns"). Here's the routine that does this
static void
doSplinesExample()
{
SEXP e, result;
int errorOccurred;
// create and evaluate 'library(splines)'
PROTECT(e = lang2(install("library"), mkString("splines")));
R_tryEval(e, R_GlobalEnv, &errorOccurred);
if (errorOccurred) {
// handle error
}
UNPROTECT(1);
// 'options(FALSE)' ...
PROTECT(e = lang2(install("options"), ScalarLogical(0)));
// ... modified to 'options(example.ask=FALSE)' (this is obscure)
SET_TAG(CDR(e), install("example.ask"));
R_tryEval(e, R_GlobalEnv, NULL);
UNPROTECT(1);
// 'example("ns")'
PROTECT(e = lang2(install("example"), mkString("ns")));
R_tryEval(e, R_GlobalEnv, &errorOccurred);
UNPROTECT(1);
}
Compile and run
We're now ready to put everything together. The compiler needs to know where the headers and libraries are
g++ -I/home/user/bin/R-devel/include -L/home/user/bin/R-devel/lib -lR embed.cpp
The compiled application needs to be run in the correct environment, e.g., with R_HOME set correctly; this can be arranged easily (obviously a deployed app would want to take a more extensive approach) with
R CMD ./a.out
Depending on your ambitions, some parts of section 8 of Writing R Extensions are not relevant, e.g., callbacks are needed to implement a GUI on top of R, but not to evaluate simple code chunks.
Some detail
Running through that in a bit of detail... An SEXP (S-expression) is a data structure fundamental to R's representation of basic types (integer, logical, language calls, etc.). The line
PROTECT(e = lang2(install("library"), mkString("splines")));
makes a symbol library and a string "splines", and places them into a language construct consisting of two elements. This constructs an unevaluated language object, approximately equivalent to quote(library("splines")) in R. lang2 returns an SEXP that has been allocated from R's memory pool, and it needs to be PROTECTed from garbage collection. PROTECT adds the address pointed to by e to a protection stack, when the memory no longer needs to be protected, the address is popped from the stack (with UNPROTECT(1), a few lines down). The line
R_tryEval(e, R_GlobalEnv, &errorOccurred);
tries to evaluate e in R's global environment. errorOccurred is set to non-0 if an error occurs. R_tryEval returns an SEXP representing the result of the function, but we ignore it here. Because we no longer need the memory allocated to store library("splines"), we tell R that it is no longer PROTECT'ed.
The next chunk of code is similar, evaluating options(example.ask=FALSE), but the construction of the call is more complicated. The S-expression created by lang2 is a pair list, conceptually with a node, a left pointer (CAR) and a right pointer (CDR). The left pointer of e points to the symbol options. The right pointer of e points to another node in the pair list, whose left pointer is FALSE (the right pointer is R_NilValue, indicating the end of the language expression). Each node of a pair list can have a TAG, the meaning of which depends on the role played by the node. Here we attach an argument name.
SET_TAG(CDR(e), install("example.ask"));
The next line evaluates the expression that we have constructed (options(example.ask=FALSE)), using NULL to indicate that we'll ignore the success or failure of the function's evaluation. A different way of constructing and evaluating this call is illustrated in R-devel/tests/Embedding/RParseEval.c, adapted here as
PROTECT(tmp = mkString("options(example.ask=FALSE)"));
PROTECT(e = R_ParseVector(tmp, 1, &status, R_NilValue));
R_tryEval(VECTOR_ELT(e, 0), R_GlobalEnv, NULL);
UNPROTECT(2);
but this doesn't seem like a good strategy in general, as it mixes R and C code and does not allow computed arguments to be used in R functions. Instead write and manage R code in R (e.g., creating a package with functions that perform complicated series of R manipulations) that your C code uses.
The final block of code above constructs and evaluates example("ns"). Rf_tryEval returns the result of the function call, so
SEXP result;
PROTECT(result = Rf_tryEval(e, R_GlobalEnv, &errorOccurred));
// ...
UNPROTECT(1);
would capture that for subsequent processing.
There is Rcpp which allows you to easily extend R with C++ code, and also have that C++ code call back to R. There are examples included in the package which show that.
But maybe what you really want is to keep your C++ program (i.e. you own main()) and call out to R? That can be done most easily with
RInside which allows you to very easily embed R inside your C++ application---and the test for library, load if needed and function call are then extremely easy to do, and the (more than a dozen) included examples show you how to. And Rcpp still helps you to get results back and forth.
Edit: As Martin was kind enough to show things the official way I cannot help and contrast it with one of the examples shipping with RInside. It is something I once wrote quickly to help someone who had asked on r-help about how to load (a portfolio optimisation) library and use it. It meets your requirements: load a library, accesses some data in pass a weights vector down from C++ to R, deploy R and get the result back.
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
//
// Simple example for the repeated r-devel mails by Abhijit Bera
//
// Copyright (C) 2009 Dirk Eddelbuettel
// Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois
#include <RInside.h> // for the embedded R via RInside
int main(int argc, char *argv[]) {
try {
RInside R(argc, argv); // create an embedded R instance
std::string txt = "suppressMessages(library(fPortfolio))";
R.parseEvalQ(txt); // load library, no return value
txt = "M <- as.matrix(SWX.RET); print(head(M)); M";
// assign mat. M to NumericMatrix
Rcpp::NumericMatrix M = R.parseEval(txt);
std::cout << "M has "
<< M.nrow() << " rows and "
<< M.ncol() << " cols" << std::endl;
txt = "colnames(M)"; // assign columns names of M to ans and
// into string vector cnames
Rcpp::CharacterVector cnames = R.parseEval(txt);
for (int i=0; i<M.ncol(); i++) {
std::cout << "Column " << cnames[i]
<< " in row 42 has " << M(42,i) << std::endl;
}
} catch(std::exception& ex) {
std::cerr << "Exception caught: " << ex.what() << std::endl;
} catch(...) {
std::cerr << "Unknown exception caught" << std::endl;
}
exit(0);
}
This rinside_sample2.cpp, and there are lots more examples in the package. To build it, you just say 'make rinside_sample2' as the supplied Makefile is set up to find R, Rcpp and RInside.

How the buffer of cout work?

I know that cout have buffer several days ago, and when I google it, it is said that the buffer is some like a stack and get the output of cout and printf from right to left, then put them out(to the console or file)from top to bottem. Like this,
a = 1; b = 2; c = 3;
cout<<a<<b<<c<<endl;
buffer:|3|2|1|<- (take “<-” as a poniter)
output:|3|2|<- (output 1)
|3|<- (output 2)
|<- (output 3)
Then I write a code below,
#include <iostream>
using namespace std;
int c = 6;
int f()
{
c+=1;
return c;
}
int main()
{
int i = 0;
cout <<"i="<<i<<" i++="<<i++<<" i--="<<i--<<endl;
i = 0;
printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );
cout<<f()<<" "<<f()<<" "<<f()<<endl;
c = 6;
printf("%d %d %d\n" , f() , f() ,f() );
system("pause");
return 0;
}
Under VS2005, the output is
i=0 i++=-1 i--=0
i=0 i++=-1 i--=0
9 8 7
9 8 7
It seems that the stack way is right~
However, I read C++ Primer Plus yesterday, and it is said that the cout work from left to right, every time return an object(cout), so "That’s the feature that lets you concatenate output by using insertion". But the from left to right way can not explain cout<
Then Alnitak tell me that, "The << operator is really ostream& operator<<(ostream& os, int), so another way of writing this is:
operator<< ( operator<< ( operator<< ( cout, a ), b ), c )",
If the rightest argument is first evaluated, it can be some explained.
Now I'm confused about how cout's buffer work, can somebody help me?
You are mixing a lot of things. To date:
Implementation details of cout
Chained calls
Calling conventions
Try to read up on them separately. And don't think about all of them in one go.
printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );
The above line invokes undefined behavior. Read the FAQ 3.2. Note, what you observe is a side-effect of the function's calling convention and the way parameters are passed in the stack by a particular implementation (i.e. yours). This is not guaranteed to be the same if you were working on other machines.
I think you are confusing the order of function calls with buffering. When you have a cout statement followed by multiple insertions << you are actually invoking multiple function calls, one after the other. So, if you were to write:
cout << 42 << 0;
It really means: You call,
cout = operator<<(cout, 42)
and then use the return in another call to the same operator as:
cout = operator<<(cout, 0)
What you have tested by the above will not tell you anything cout's internal representation. I suggest you take a look at the header files to know more.
Just as a general tip, never ever use i++ in the same line as another usage of i or i--.
The issue is that function arguments can be evaluated in any order, so if your function arguments have any side-effects (such as the increment and decrement operations) you can't guarantee that they will operate in the order you expect. This is something to avoid.
The same goes for this case, which is similar to the actual expansion of your cout usage:
function1 ( function2 ( foo ), bar );
The compiler is free to evaulate bar before calling function2, or vice versa. You can guarantee that function2 will return before function1 is called, for example, but not that their arguments are evaluated in a specific order.
This becomes a problem when you do something like:
function1 ( function2 ( i++), i );
You have no way to specify whether the "i" is evaluated before or after the "i++", so you're likely to get results that are different than you expect, or different results with different compilers or even different versions of the same compiler.
Bottom line, avoid statements with side-effects. Only use them if they're the only statement on the line or if you know you're only modifying the same variable once. (A "line" means a single statement plus semicolon.)
What you see is undefined behavior.
Local i and global c are added/subtracted multiple times without sequence point. This means that values you get can be about anything. Depends on compiler, possibly also processor architecture and number of cores.
The cout buffer can be thought as queue, so Alnitak is right.
In addition to the other answers which correctly point out that you are seeing undefined behavior, I figured I'd mention that std::cout uses an object of type std::streambuf to do its internal buffering. Basically it is an abstract class which represents of buffer (the size is particular to implementation and can even be 0 for unbufferd stream buffers). The one for std::cout is written such that when it "overflows" it is flushed into stdout.
In fact, you can change the std::streambuf associated with std::cout (or any stream for that matter). This often useful if you want to do something clever like make all std::cout calls end in a log file or something.
And as dirkgently said you are confusing calling convention with other details, they are entirely unrelated to std::cout's buffering.
In addition, mixing output paradigms (printf and cout) are implementation specific.