Function not returning what I expected

Hi, I have the following function:

1
2
3
4
5
6
7
8
9
10
11
12
/* proposal distribution */
void dist(double paraest[2],double sigscale[2][2],int npara){
    paraest[0]=0.5;
    paraest[1]=0.5;

    sigscale[0][0]=0.01;
    sigscale[0][1]=0;
    sigscale[1][0]=0;
    sigscale[1][1]=0.01;

    npara=2;
}


The corresponding code in main() looks like below:

1
2
3
4
5
6
    /* proposal distribution */
    double paraest[2];
    double sigscale[2][2];
    int npara;
    dist(paraest,sigscale,npara);
    std::cout << "npara=" << npara << endl;


The output looks like below:


npara=919361868


Does anyone know why npara does not equal 2 in the output, please? Thank you very much.
Last edited on
Does anyone know why npara does not equal 2 in the output, please?

Since you passed npara by value into the function any changes made to this variable in the function are lost when the function returns. You should try passing the variable by reference if you want the changes to be reflected in the calling function. Or you could just return this value to the calling function instead.

1
2
3
4
5
6
int dist(double paraest[2],double sigscale[2][2])
{
   ...

   return npara;
}


@jlb: so the arrays are okay if passed this way because they are references themselves? And if there are multiple ints or doubles to return, passing by reference would be like &npara?

1
2
3
4
5
6
7
8
9
10
11
12
13
/* proposal distribution */
void dist(double paraest[2],double sigscale[2][2],int &npara,int &mpara){
    paraest[0]=0.5;
    paraest[1]=0.5;

    sigscale[0][0]=0.01;
    sigscale[0][1]=0;
    sigscale[1][0]=0;
    sigscale[1][1]=0.01;

    npara=2;
    mpara=3;
}
Last edited on
so the arrays are okay if passed this way because they are references themselves?

No arrays are passed by pointer, not by reference.

And if there are multiple ints or doubles to return, passing by reference would be like &npara?

Yes.
@jlb: Noted. Although the current way I am passing arrays seems to work?
Because, as jlb said, you're passing a pointer to the contents of the array. You can change the array contents, but because the pointer has the same value inside and outside the function, the pointer will point to those changed values inside and outside the function.

If you changed the value of the pointer itself inside the function, it wouldn't change the value of the pointer in the calling code.
@MikeyBoy: I see. Well it is convenient then, to pass a pointer without having to write * anywhere.
Last edited on
closed account (48T7M4Gy)
This might make the picture clearer. It is good practice to deliberately use different variable names in a function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

/* proposal distribution */
void dist(double p[2],double q[2][2],int np)
{
    p[0]=0.5;
    p[1]=0.5;
    
    q[0][0]=0.01;
    q[0][1]=0;
    q[1][0]=112.345;
    q[1][1]=0.01;
    
    np = 2;
}

int main()
{
    /* proposal distribution */
    double paraest[2];
    double sigscale[2][2];
    int npara = 7;
    std::cout << "npara=" << npara << std::endl;
    std::cout << "sigscale[1][0] = " << sigscale[1][0] << std::endl;
    
    dist(paraest,sigscale,npara);
    
    std::cout << "npara=" << npara << std::endl;
    std::cout << "sigscale[1][0] = " << sigscale[1][0] << std::endl;
    
    return 0;
}


npara=7
sigscale[1][0] = 0
npara=7
sigscale[1][0] = 112.345
Program ended with exit code: 0


And if you change dist to
void dist(double p[2],double q[2][2],int &np)
you get ...
npara=7
sigscale[1][0] = 0
npara=2
sigscale[1][0] = 112.345
Program ended with exit code: 0
@lifeisgood:

With regards to the title of this thread, "return" does not mean "output to the console". It means passing a value back to the calling code from a function.

You're going to confuse yourself and other people if you get those mixed up.
@kemort: this is very helpful, thank you very much. I will follow this advice.

@MikeyBoy: noted, thanks!

At the moment I encountered this problem:

Line 210: error: invalid types 'double[int]' for array subscript


The code is here:

https://github.com/flowerysleeves/RandomWalkMH/blob/master/main.cpp

Does anyone know what is wrong, please? The dimensions of arrays that I pass to the function should be the same as the ones used in the function.. The first time I call this function is on line 258.
Last edited on
Your function prototype at line 202 says:
void median(double *median_parasim_j,double *parasim_j)
“median_parasim_j” and “parasim_j” are pointers to double.
But five lines below:
parasim_j[i][h]>parasim_j[i+1][h]
you use the latter as a multi-dimensional array.

Anyway, not to depress you, but, even ignoring the warnings, my compiler rattles off a long list of errors:
main.cpp: In function 'void median(double*, double*)':
main.cpp:210:30: error: invalid types 'double[int]' for array subscript
             if(parasim_j[i][h]>parasim_j[i+1][h]){
                              ^
main.cpp:210:48: error: invalid types 'double[int]' for array subscript
             if(parasim_j[i][h]>parasim_j[i+1][h]){
                                                ^
main.cpp:211:17: error: 'temp' was not declared in this scope
                 temp=parasim_j[i][h];
                 ^~~~

main.cpp:211:36: error: invalid types 'double[int]' for array subscript
                 temp=parasim_j[i][h];
                                    ^
main.cpp:212:31: error: invalid types 'double[int]' for array subscript
                 parasim_j[i][h]=parasim_j[i+1][h];
                               ^
main.cpp:212:49: error: invalid types 'double[int]' for array subscript
                 parasim_j[i][h]=parasim_j[i+1][h];
                                                 ^
main.cpp:213:33: error: invalid types 'double[int]' for array subscript
                 parasim_j[i+1][h]=temp;
                                 ^
main.cpp:218:42: error: 'j' was not declared in this scope
         median_parasim_j[h] = (parasim_j[j-1][h]+parasim_j[j][h])/2;
                                          ^
main.cpp: At global scope:
main.cpp:223:30: error: 'nsim' was not declared in this scope
 void storages(double parasim[nsim][npara],double likesim[nsim],double postsim[nsim],double &nsim,double &npara,int pshape[2],double pmean[2],double psdd[2],int pmask[2],int pmaskinv[2],int pfix[2],double Y[nT],double X[nT],double paraold[2],double postold,double likeold){
                              ^~~~

main.cpp:223:36: error: 'npara' was not declared in this scope
 void storages(double parasim[nsim][npara],double likesim[nsim],double postsim[nsim],double &nsim,double &npara,int pshape[2],double pmean[2],double psdd[2],int pmask[2],int pmaskinv[2],int pfix[2],double Y[nT],double X[nT],double paraold[2],double postold,double likeold){
                                    ^~~~~
main.cpp:223:42: error: expected ')' before ',' token
 void storages(double parasim[nsim][npara],double likesim[nsim],double postsim[nsim],double &nsim,double &npara,int pshape[2],double pmean[2],double psdd[2],int pmask[2],int pmaskinv[2],int pfix[2],double Y[nT],double X[nT],double paraold[2],double postold,double likeold){
                                          ^
main.cpp:223:43: error: expected unqualified-id before 'double'
 void storages(double parasim[nsim][npara],double likesim[nsim],double postsim[nsim],double &nsim,double &npara,int pshape[2],double pmean[2],double psdd[2],int pmask[2],int pmaskinv[2],int pfix[2],double Y[nT],double X[nT],double paraold[2],double postold,double likeold){
                                           ^~~~~~
main.cpp: In function 'void moment(double, double, double, double)':
main.cpp:318:37: error: invalid type argument of unary '*' (have 'double')
     double nsim=sizeof(irf)/sizeof(*irf);
                                     ^~~
main.cpp:319:22: error: invalid type argument of unary '*' (have 'double')
     double H=sizeof(*irf)/sizeof(**irf);
                      ^~~
main.cpp:319:36: error: invalid type argument of unary '*' (have 'double')
     double H=sizeof(*irf)/sizeof(**irf);
                                    ^~~
main.cpp:321:17: error: cannot convert 'double' to 'double*' for argument '1' to 'void median(double*, double*)'
     median(y,irf);
                 ^
main.cpp:323:21: error: size of array 'temp' has non-integral type 'double'
     double temp[nsim];
                     ^
main.cpp:328:9: error: 'h' was not declared in this scope
     for(h=0;h<H;h++){
         ^
main.cpp:329:13: error: 'i' was not declared in this scope
         for(i=0;i<nsim;i++){
             ^
main.cpp:332:23: error: invalid operands of types 'double [1]' and 'double' to binary 'operator+'
         sort(temp,temp+nsim);
                   ~~~~^~~~~
main.cpp:332:9: error: 'sort' was not declared in this scope
         sort(temp,temp+nsim);
         ^~~~
main.cpp:332:9: note: suggested alternative: 'qsort'
         sort(temp,temp+nsim);
         ^~~~
         qsort
main.cpp:333:13: error: 'i' was not declared in this scope
         for(i=0;i<nsim;i++){
             ^
main.cpp:336:23: error: invalid types 'double[int]' for array subscript
         y05[h]=irf[n05][h];
                       ^
main.cpp:337:23: error: invalid types 'double[int]' for array subscript
         y95[h]=irf[n95][h];
                       ^
main.cpp:344:39: error: invalid type argument of unary '*' (have 'double')
     double H=sizeof(*wshock)/sizeof(**wshock);
                                       ^~~~~~
main.cpp:345:23: error: invalid type argument of unary '*' (have 'double')
     double n=sizeof(**wshock)/sizeof(***wshock);
                       ^~~~~~
main.cpp:345:41: error: invalid type argument of unary '*' (have 'double')
     double n=sizeof(**wshock)/sizeof(***wshock);
                                         ^~~~~~
main.cpp:347:20: error: size of array 'y05' has non-integral type 'double'
     double y05[H][n];
                    ^
main.cpp:347:20: error: size of array 'y05' has non-integral type 'double'
main.cpp:347:20: error: declaration of 'double y05 [1][1]' shadows a parameter
main.cpp:348:20: error: size of array 'y20' has non-integral type 'double'
     double y20[H][n];
                    ^
main.cpp:348:20: error: size of array 'y20' has non-integral type 'double'
main.cpp:348:20: error: declaration of 'double y20 [1][1]' shadows a parameter
main.cpp:349:12: error: declaration of 'double y50' shadows a parameter
     double y50=median(wshock);
            ^~~
main.cpp:349:29: error: too few arguments to function 'void median(double*, double*)'
     double y50=median(wshock);
                             ^
main.cpp:350:20: error: size of array 'y80' has non-integral type 'double'
     double y80[H][n];
                    ^
main.cpp:350:20: error: size of array 'y80' has non-integral type 'double'
main.cpp:350:20: error: declaration of 'double y80 [1][1]' shadows a parameter
main.cpp:351:20: error: size of array 'y95' has non-integral type 'double'
     double y95[H][n];
                    ^
main.cpp:351:20: error: size of array 'y95' has non-integral type 'double'
main.cpp:351:20: error: declaration of 'double y95 [1][1]' shadows a parameter
main.cpp:353:5: error: 'sort' was not declared in this scope
     sort(wshock,wshock+100000);
     ^~~~

main.cpp:355:5: error: 'n05' was not declared in this scope
     n05=floor(0.05*nsim+0.5);
     ^~~

main.cpp:358:5: error: 'n20' was not declared in this scope
     n20=floor(0.2*nsim+0.5);
     ^~~

main.cpp:361:5: error: 'n80' was not declared in this scope
     n80=floor(0.8*nsim+0.5);
     ^~~

main.cpp:364:5: error: 'n95' was not declared in this scope
     n95=floor(0.95*nsim+0.5);
     ^~~
...

Last edited on
@enoizat: yeah, I was referencing to the beginning of arrays, which are made of doubles. I have those errors as well, so I am trying to fix them one by one.

So now I have this error on line 268:

error: cannot convert 'double (*)[1]' to 'double**' for argument '2' to 'void median(double*, double**)'


The code is updated here: https://github.com/flowerysleeves/RandomWalkMH/blob/master/main.cpp
Last edited on
Well, you have declared ‘parasim_j’ as a bidimensional array of double
double parasim_j[2*j-2][1];
and you pass it to a function which asks for a pointer to pointer to double
void median(double *median_parasim_j,double **parasim_j)
There are several workarounds, e.g.
http://www.cplusplus.com/forum/general/103256/

Once you’ve solved that single issue, anyway that line of code won’t do what you want, because a void function can’t return any value, so your std::cout statement won’t have anything to display.

May I ask you what’s the point of correcting a single line of code between hundreds of different errors?
If I were in your shoes, I’d prefer restarting from scratch this way:
- write a simple main();
- add one by one the functions I need;
- test each of them extensively before adding the next.

While I’m at it, I’d also try to:
- remove all those C-style ‘#define’. Some of them are also unused. You can safely substitute ‘constexpr’ for the ones you really need.

- Try to see if some of the data I use can be ‘grouped’ together.
For example, your function
void objfcn(double retp1,double retp2,double para[2],int pshape[2],double pmean[2],double pstdd[2],int pmask[2],int pmaskinv[2],int pfix[2],double lubound[2][2],double Y[nT],double X[nT])
is nearly illegible for me.
I’d try to put all that data into a struct and than pass an instance of that struct.

- Substitute std::vectors or std::arrays or std::valarrays for my C-style arrays. It can make life much easier.
Last edited on
@Enoizat: I am following your suggestions. They are very good and very instructional. Thank you so much! I will get back to you about my progress.
You’re welcome, @lifeisgood, and every feedback will be appreciated, but I can’t boast any authorship in what I suggested :-)
Maybe you could be interested in Agile:
http://www.agilenutshell.com/
Or, if have a quarter an hour to spend on it:
https://www.youtube.com/watch?v=Z9QbYZh1YXY

Agile is not something which needs to be ‘studied’, is just something it’s useful to be in touch with at one’s own leisure.

Happy coding!
@Enoizat: I went to the website and also watched the video. It is awesome! Will recommend to relevant individuals when I get a chance, too!

At the moment I am confused about this:
On line 595 in main() I am declaring an array. When I try to get its size, the output would be 16. But when I feed a pointer to the array in the function called "posterior" on line 252, the size becomes 4. I am very puzzled why the size shrinks so much.

Here is the code: https://github.com/flowerysleeves/RandomWalkMH/blob/master/main.cpp
But when I feed a pointer to the array in the function called "posterior" on line 252, the size becomes 4.

What is the size of a pointer on your system? How are you trying to determine the size of the array?

Remember when you pass an array to a function you are passing a pointer, not the actual array.

I havent’ check your new code to verify if my hypothesis is correct, but I hope I’ve guessed what you are asking about.
C-style arrays and pointers are not exactly the same thing.
Brian W. Kernighan, Dennis M. Ritchie, The C programming Language second edition, 1988, chapter 5 Pointers and Arrays:
...A pointer is a group of cell [...] that can hold an address...
...Any operation that can be achieved by array subscripting can also be done with pointers...
...There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal...


The following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <limits>

struct MyStruct {
    double first    {0.0};
    double second   {0.0};
    double third    {0.0};
};

void waitForEnter();

int main()
{
    MyStruct mstr;
    MyStruct myarr[5];
    MyStruct* p_mystr {nullptr};
    MyStruct* p_mystr2 = myarr;
    std::cout <<   "The size of an instance of MyStruct is      " << sizeof(mstr)
              << "\nthe size of an array of five MyStructs is   " << sizeof(myarr)
              << "\nthe size of a pointer to MyStruct is        " << sizeof(p_mystr)
              << "\neven if it points to an array of MyStructs: " << sizeof(p_mystr2)
              << "\nSurprise! The size of a pointer to int is:  " << sizeof(int*)
              << "\n...and the size of a pointer to char is:    " << sizeof(char*)
              << "\n...and the size of a pointer to double is:  " << sizeof(double*)
              << '\n';
    waitForEnter();
    return 0;
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


In my machine prints:
The size of an instance of MyStruct is      24
the size of an array of five MyStructs is   120
the size of a pointer to MyStruct is        8
even if it points to an array of MyStructs: 8
Surprise! The size of a pointer to int is:  8
...and the size of a pointer to char is:    8
...and the size of a pointer to double is:  8

Press ENTER to continue...


The (simplified) idea is: a pointer is just a variable which contains an address. Period.
No matter what it points to, the size of a pointer will always be the same, because it just needs to hold an (integer) number, which is an address.
A C-style array represents a block of memory. The size of a C-style array depends on what’s there in that block of memory (how many objects * their size).
That block of memory has an address. When you pass an array as a parameter of a function, you are passing its address (which is, of course, the address of its first element).
So, inside the function, what you get is a pointer.

What’s above I think clarifies why std::vectors are so easier to use than C-style arrays.
@jlb: thanks for the info!

@Enoizat: yes, you did mention in your earlier response that I should replace arrays with std:: vectors. I have also seen them in other places too. Also I really need to learn structs..
Last edited on
Topic archived. No new replies allowed.