Greetings and Quick question about arrays as arguments in functions

Hi everybody,
My first post and I am so glad to be here.
This is a part of code that will calculate some simple calculation.
The thing is that the result gives no output. I simply get black window and after a couple of seconds I get "process returned -whatever and press any key...".

Sorry this is my first post here and I might be not very well aware of the posting and asking policies.

Thanks in advance for your helps

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  #include <iostream>
#include <math.h>
#define row 10
#define column 10

using namespace std;


//void update(float **old,float **x);
////////////////////////////////

///// Global variables/////
int x0 = 0;
int z0 = 0; // Boundaries
int x[10];
int y[10];
int imax = 10; //number of cells
int jmax = 10;
float deltaX=0.2;  // Cells width
float deltaY=0.2;
void initialize(float** );

int main()
{
  float t = 0.0, deltaT = 0.5;    //timer
    int i,j=10;
    float **dens_old;

initialize( dens_old );

for(int i=0;i<imax;i++)
{
    for (int j=0;j<jmax;j++)
    {
        cout<<"initail values = "<<dens_old[i][j]<<endl;
    }
}


}
////////////////////////////////
void initialize (float** dens_old){

for (int j=0 ; j<jmax ; j++){
    x[j] = x0 + deltaX*j;
}
for (int i=0 ; i<imax ; i++){
    y[i] = z0 + deltaY*i;
}
 for (int j=0 ; j<jmax ; j++)
 {
     for (int i=0 ; i<imax ; i++)
     {
         dens_old[j][i]=0.0; //// initial density-------might be changed according to extra info
     }
 }


}
Hi Ferik,

First thing to point out is that pointers do not equal arrays.
You have a float** pointer, dens_old. This is not an array, it is not initialized to any valid value, and you have not allocated any space to initialize it to hold valid values.

Search for "[name of your compiler/IDE] with warnings" to figure out how to enable warnings when compiling your code. One of the warnings in GCC (with -Wall) is that dens_old is being used uninitialized.

You can define a 2D array like so: float dens_old[10][10] = {};
The = {} part of it initializes all elements to 0.

This can be passed to a function like so:
1
2
3
4
5
6
7
8
9
10
void foo(float arr[][column])
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < column; j++)
        {
            arr[i][j] = /* ... */;
        }
    }
}


_____________________________________

PS: avoid using macros like
#define row 10
#define column 10

You can use const ints instead,
1
2
const int row = 10;
const int column = 10;

at no extra cost.
This also makes your imax/jmax variables redundant.
Last edited on
Hello Ferik,

in addition to what Ganado has said it is best to avoid using global variables as the whole file has access to them. This may seem easier, but anything can change these variables and it may be difficult to find where something went wrong.

Best to define the variables in main and pass them to functions that need them.

Global variables that start with "const" or "constexpr" are OK because they can not be changed.

As Ganado suggested I would do this:
1
2
constexpr int ROW{ 10 };
constexpr int COL{ 10 };

This format is from the C++11 standards on. I think it is much easier to work with. The capital letters help to remind you that the variable is defined as a constant. How you name the variables is always your choice.

The other thing I noticed is the use of the {}s in "main" is one style, but the {}s in the function are different. It really helps when you keep a consistant way of doing something.

Hope that helps,

Andy
Thanks Ganado and Andy for your answers.

Sorry I did not fully understand and I tried to follow it and this time i got error.

I also had read in lots of books that arrays and pointers are closely related and I was expecting it to work.

I also am using free IDE (code block) and can not use C++ 11.

Will you please specifically mention which line should be modified and how?

Ferik wrote:
Will you please specifically mention which line should be modified and how?

Change line 21 to
void initialize(float [row][column]);
Change line 27 to
float dens_old[row][column];
Change line 42 to
void initialize (float dens_old[row][column]){

These will get it to compile and "run" (in cpp.sh anyway). However, this code is asking for trouble down the line and you should rewrite it. You should read @Ganado's post in particular about arrays/pointers. Pointers are not trivial for 2-d arrays (and would begin to look silly for 3-d arrays).

Don't use so many global variables. You are also apparently (trying to) use row/column, imax/jmax and 10 for precisely the same thing. You can (and probably should) use imax instead of row and jmax instead of column, but only if the declarations of imax and jmax are qualified by 'const'; e.g. const int imax = 10;.


Also:
y[i] = z0 + deltaY*i;
Mixing y and z like that is asking for trouble. It is also considerably more common to use i to index x values and j to index y values.


Line 35: cout<<"initail values = "<<dens_old[i][j]<<endl;
Line 54: dens_old[j][i]=0.0;
They may just be counting variables at present, but unless you are consistent with the order of i and j you are going to get very confused later.


Ferik wrote:
I also am using free IDE (code block) and can not use C++ 11.

That does not follow.



Whatever book you are following is not helping you. Use double rather than float for scientific applications. And DON'T try to patch together different snippets of code in the hope that they will work; aim to understand what you are doing and plan coherently. You have a lot of redundant variables as well.

Last edited on
I also had read in lots of books that arrays and pointers are closely related and I was expecting it to work.

Related yes, but you forgot the details.

An array refers to a block of memory that contains values.
A pointer is a small variable that contains one value: an address.

Think an array as a house and pointer as a postit note that has an address of a house. Your float **dens_old; writes a postit that has random characters on it. They might look like an address, but even if there is a house, it won't be your house. Crashing in into strangers house is not ok.

In this the house is real and the note we give to the function is valid; it gets the address of your house:
1
2
3
void func( float* note );
float house[42];
func( house );


Related example:
int foo = 7;
1
2
3
4
int* bar; // uninitialized pointer
int* gaz = &foo; // initialized pointer
*bar = 42; // error, address unknown
*gaz = 42; // ok, effectively does: foo = 42; 

Perhaps you were on a chapter about dynamic memory allocation?
That is a good to understand topic, but you should prefer the C++ Standard Library Containers that do the manual chores for you, safely.


I also am using free IDE (code block) and can not use C++ 11.

IDE uses a compiler and that compiler can be replaced.

Alternatively, the current compiler might already have support for recent C++, but requires explicit enablement. The IDE should offer ways to pass such (command line) options to the compiler.
Last edited on
2-d constructs are a major aggravation, and even worse with pointers. If you can use vector that would help a lot. If its a constant 10x10, you can allocate as a 2d array and cast to 1-d (eg to memcpy all zeros into it) as needed if you can't use vector. There is no reason to use dynamic memory for such a small piece of memory.
Thank you so much fellas for great insights and big helps. Yes now I can see where I was doing wrong.

I was partly aware but had totally forgotten the case of 2D arrays and its relation to pointers. ( I have not done 3d arrays in my life yet).

With modification that lastchance mentioned I managed to get it to work.

Dear Keskiverto, I did not totally get your point on C++11. I tried to add or modify (not sure about what I have to use) the code::block to run C++ 11 and I always got errors.

As you can see my programs have strong C accent and I have not been able to update to C++ effectively.

Dear lastchance, I need those global variables and this is only a part of the code. Are you (and other memebrs) entirely against it? I know using global variables are a bit risky but am not sure how much should I avoid them.

Sorry If my question was too dumb but now I feel great with your help.

Thanks again fellas for your time and effort.

I'm not completely against global variables - as long as you keep them to a minimum, and don't have unnecessary duplication.

Note that if you use vectors rather than fixed arrays you would automatically pass their size as part of the vector.

If you need to transfer a lot of variables then you could make them the data members of a single struct - in your case it would be convenient to have a grid struct, for example.
Instead of using globals (save for your "row" and "column" const values), you can declare most of them in main, and then pass the variables to functions as needed.

e.g.
1
2
3
4
void initialize(int x[], int y[], float arr[][column])
{
    // ...
}


initialize(x, y, dens_old);

The less implicit/hidden state a function depends on, the more maintainable it is.
Last edited on
Topic archived. No new replies allowed.