1

I am trying to pass array to function (*getcreditcurve). I am expecting function (*getcreditcurve) to return an array. Main function is expected to send several such array to function (*getcreditcurve), pointer function is expected to return a array to main function for different array using the logic given in pointer function (*getcreditcurve). I am not getting error but I don’t get correct value. I expect I+1 to be 3 * 0.0039 = 0.0117 and I+2 to be 4 *0.0060 = 0.0024 however I get following in excel output

'00D4F844   00D4F84C'

Even if I change the print statement to

'print << *(I1+1) << '\t' << *(I2+2) << endl;'

I get following excel out put

-9.26E+61   -9.26E+61

Can somebody help in trouble shooting please? Sorry I went through other post/question in this site but not able to get simplest way to solve this issue. I am going to use this logic to build other projects so simplified the question just to resolve main issue.

#include<iostream>
#include<cmath>
#include<fstream>
typedef double S1[5];
using namespace std;
double *getcreditcurve(double *);

int main()
{


S1 C1 = { 0.0029, 0.0039, 0.0046, 0.0052, 0.0057 };
S1 C2 = { 0.0020, 0.0050, 0.0060, 0.0070, 0.0080 };

typedef double *issuer;
issuer I1 = getcreditcurve(C1);
issuer I2 = getcreditcurve(C2);


ofstream print;
print.open("result1.xls");
    print << (I1+1) << '\t' << (I2+2) << endl;

    print.close();
    return 0;


}

double *getcreditcurve(S1 ptr)
{
const int cp = 5;
typedef double curve[cp];
curve h;

h[0] = 2 * ptr[0];
h[1] = 3 * ptr[1];
h[2] = 4 * ptr[2];
h[3] = 5 * ptr[3];
h[4] = 6 * ptr[4];

return h;
}
Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
Kausik
  • 43
  • 5
  • 5
    http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope Arrays do not copy implicitly. That's one reason why they are not very handy and should be replaced by `std::array`. – Baum mit Augen Jul 11 '15 at 22:18
  • [Scope vs. Lifetime of Variable](http://stackoverflow.com/questions/11137516) seems to be a near duplicate... storing a pointer to a variable that has gone out of scope. – Drew Dormann Jul 11 '15 at 22:32

2 Answers2

1

If you want getcreditcurve to return an array, then try this:

const int cp = 5;
typedef double curve[cp];
curve getcreditcurve(S1 ptr) {

But that gives an error error: ‘foo’ declared as function returning an array. Functions can't return C arrays. But the good news is that if you fully embrace C++ you can return std::array instead.

#include<array>
const int cp = 5;
typedef curve std::array<double,cp>;
curve getcreditcurve(S1 ptr) {

But really, std::vector is probably much better as you have more flexibility about the size.

#include<vector>

std::vector<double> getcreditcurve(std::vector<double> ptr)
{
    std::vector<double> h;
    h.push_back(2 * ptr.at(0));
    h.push_back(3 * ptr.at(1));
    h.push_back(4 * ptr.at(2));
    h.push_back(5 * ptr.at(3));
    h.push_back(6 * ptr.at(4));

    return h;
}

In fact, pretty much all problems with C arrays can be solved by std::vector. Then, in special situations, you can use std::array. But focus on std::vector for now.

Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
  • ok I will try vector but just to confirm " typedef curve std::array;" or "std::vector getcreditcurve(std::vector ptr)" is to change getcredit curve function only. I have written my ain project with lots of array. Sp more try to use array but conceptually array and vector will work same (keeping aside size issue? – Kausik Jul 11 '15 at 22:52
  • You will have to make many more changes. Basically, you should avoid `*` totally (except, of course, for multiplication). You'll have to write `vector C1 { 0.0029, 0.0039, 0.0046, 0.0052, 0.0057 };` to define C1 as a vector also. I know this seems like a lot of work, but it really is better to just avoid `*`-pointers in C++ – Aaron McDaid Jul 11 '15 at 23:08
  • Also, you must be *very* clear when you use the word "array". You should say "C array" when discussing the kind of arrays your are using now `e.g. char c[5]`, and you should say "`std::array`" when talking about the improved arrays in C++11. I will try to be clear in future. Most people, when they say "array", mean "C array", but it might be better to be clear always – Aaron McDaid Jul 11 '15 at 23:10
  • I see another comment related to "storing a pointer to a variable that has gone out of scope." So do I have to use "new" feature in addition asI am paasing different arrays – Kausik Jul 11 '15 at 23:23
  • @Kausik, if you use `std::vector` or `std::array`, and if you avoid pointers and avoid `new` and `delete`, then you will not need to worry about memory allocation and problems such as pointers going out of scope. But yes, if you have a C array as a local variable, then you should not return it. (I might now add another answer to show an easy way to solve this) – Aaron McDaid Jul 12 '15 at 08:45
0

It's not possible to return a C array from a function. There are other things you can return, such as std::vector or std::array. You should consider redesigning your application around those two instead.

But if you really need to use C arrays in C++, I suggest that instead of trying to return an array from getcreditcurve, you pass an extra array into getcreditcurve which will be used to store the result. This is called an output parameter.

void getcreditcurve(double*, double *);

This would solve the "scope" problem. The caller (main) would then create the array before calling getcreditcurve and would then pass that to getcreditcurve. As a result, getcreditcurve does not have to take responsibility for creating (or destroying) any object.

double I1[5];
getcreditcurve(I1, C1); // will store its result on `I1`.

This might be the easiest option if you really really need to get this working as soon as possible.


If you are willing to make some further changes, you can make a much safer program. The short term goal is to abolish all uses of * (except to use it for multiplication).

C arrays cannot be passed by value, in particular they cannot be returned. There are other funky things you can do (passing special pointers), but the best thing to do with C arrays is to pass them by reference. In C++, reference-passing behaviour is quite consistent and works well.

// http://stackoverflow.com/questions/31362360/unexpected-value-return-by-array-variable
#include<iostream>
#include<cmath>
#include<fstream>
typedef double S1[5];
using namespace std;

/* In the following declaration, the two parameters
 * are taken by reference (note the '&').
 * This is almost always the best way to pass arrays.
 *
 * Also, this is a template where N is automatically
 * set to the correct number of parameters. This nice
 * automatic behaviour is possible only because the
 * array is taken by reference.
 *
 * Finally, note that the second reference, for 'input',
 * has 'const'. This is to emphasize that 'input' is for input,
 * that getcreditcurve will not be allowed to modify the input argument.
 */
template<size_t N>
void getcreditcurve(double (&output)[N],const double (&input)[N]);

int main()
{


    /* S1 is the type - array of five doubles */
    /* Here declare and initialize C1 and C2 as two variables
     * of this type */
    S1 C1 = { 0.0029, 0.0039, 0.0046, 0.0052, 0.0057 };
    S1 C2 = { 0.0020, 0.0050, 0.0060, 0.0070, 0.0080 };

    // create the two output arrays first, within main
    S1 I1;
    S1 I2;
    // call getcreditcurve, passing in the output and input arrays
    getcreditcurve(I1,C1);
    getcreditcurve(I2,C2);


    ofstream print;

    /* you can't create Excel(.xls) files in C++ easily
     * Better to just create a .csv file instead
     * csv = comma-separated values
     */
    print.open("result1.csv");
    print << I1[0] << ',' << I2[3] << endl;

    print.close();
    return 0;

}

template<size_t N>
void getcreditcurve(double (&output)[N],const double (&input)[N])
{
    output[0] = 2 * input[0];
    output[1] = 3 * input[1];
    output[2] = 4 * input[2];
    output[3] = 5 * input[3];
    output[4] = 6 * input[4];
}

But seriously, you really should just ditch C arrays entirely. This is C++, not C. Use std::vector<double> instead.

Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88