0

there are a lot of explanations about these things, but I cannot seem to get the basic concepts with variables between .h and .c files. I cannot change the layout, so to speak, of the files and their contents. Here is my code:

driver.h

#ifndef VARIABLES_H
#define VARIABLES_H

//size limits for Pk
double limit_x;
double limit_y;
double limit_z;

//grid cells
int cells_x = 500;
int cells_y = 500;
int cells_z = 500;

extern double particles[][3];

extern double randMtoN();
extern int populateParticles();

#endif

driver.c

#include "driver.h"
#include <stdio.h>
#include <stdlib.h>    
#include <time.h>
#include <math.h>   

int main(int argc, char **argv) {

    //seed rand()
    srand((unsigned)time(NULL));

    //add particles to box 
    limit_x = 200;
    limit_y = 200;
    limit_z = 200;
    int particle_no = 10000;

    double particles[particle_no][3];

    //memset(particles, 0, sizeof particles);

    populateParticles(limit_x, limit_y, limit_z, particle_no, particles);
    printf("l\n");

    printf("%d %f %f %f", 1, particles[0][0], particles[0][1], particles[0][2]);         
}

functions.c:

 double randMtoN(double M, double N) {
    return M + (rand() * N);
}


int populateParticles(double limit_x, double limit_y, double limit_z, int particle_no, double **particles) {

    //double particles[particle_no][3];

    for (int i = 0; i < particle_no; i++) {

        particles[i][0] = randMtoN(0, limit_x);
        particles[i][1] = randMtoN(0, limit_y);
        particles[i][2] = randMtoN(0, limit_z);     

    }

    return 0;

}

What I get is this warning: implicit declaration of function ‘rand’ [-Wimplicit-function-declaration] return M + (rand() * N);

And then a segfault (due to the particles[][] in functions.c)

Darbininkai Broliai
  • 159
  • 1
  • 1
  • 13
  • 1
    2D arrays are not double pointers. Also, if `functions.c` uses `rand()`, it needs to `#include `. And if `driver.h` is included in separate translation units, they'll each get independent copies of the global vars -- consider `extern`. – Dmitri Jul 16 '16 at 19:52
  • Is there a way to rewrite it without the separate include in functions.c? To just have a bare function that has all access to what driver.c has? – Darbininkai Broliai Jul 16 '16 at 19:59
  • Actually, in the code you've shown, none of the global vars in `driver.h` are actually used, except `limit_x` etc. which could just as easily be local to `main()` or replaced by literals. – Dmitri Jul 16 '16 at 20:00
  • 1
    If `driver.c` needs declarations from a header file, it'll have to `#include` it... you can't really get around that. But why would that be a problem? Also, your crash probably comes from passing the 2D array of `double` (`particles` from `main()`) to a function treating it as `double **`, which is not equivalent. – Dmitri Jul 16 '16 at 20:02
  • How do I correctly pass this array(or reference to it) such that I can modify it from functions.c as a global variable? – Darbininkai Broliai Jul 16 '16 at 20:05
  • If the inner array dimension is always 3, just pass it as `double particles[][3]` instead of `double **particles` – Dmitri Jul 16 '16 at 20:09
  • Nope, still a segfault – Darbininkai Broliai Jul 16 '16 at 20:12
  • Do not (I.E. NEVER) place variable declarations (instance of the variable) in a header (*.h) file. Instead, place the variable declarations in a source (*.c) file. That way there is only one instance of the variable. Then the header file (*.h) file, to make the variables visible in other files, should contain the appropriate `extern` statements for those variables. In some linkers and depending on the options used, placing a variable declaration in a header file will result in multiple instances of that variable, which is (usually) not what is wanted. – user3629249 Jul 16 '16 at 21:01

3 Answers3

1

you have two incarnations of the limit_x etc variables. You'd have to declare all your variables with extern and without the initialization in the .h file. Then you'd have to pick one of your .c files and define and initialize the variables, there.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
1

In functions.c you have not included stdlib.h which contains the definition of rand().

fornit
  • 79
  • 1
  • 11
0

In addition to the two other answers:

And then a segfault (due to the particles[][] in functions.c)

In the file functions.c, your definition:

int populateParticles(double limit_x, double limit_y, double limit_z, int particle_no, double **particles) {…}

resulting in compiler warning:

incompatible pointer types passing 'double [particle_no][3]' to parameter of
  type 'double **' [-Wincompatible-pointer-types]

and the Segmentation fault execution error,

should be changed into:

int populateParticles(double limit_x, double limit_y, double limit_z, int particle_no, double particles[][3]) {…}

resulting in the expected behavior.

...cannot pass reference to global double[][]

NB: There is no "passing reference" in C. For further reading, please see this SO post.

Community
  • 1
  • 1
user3078414
  • 1,942
  • 2
  • 16
  • 24
  • Still get a segfault, why can't I edit values of this array dynamically in my functions.c file? – Darbininkai Broliai Jul 16 '16 at 21:17
  • This is tested and working, else I wouldn't have posted. You might have not read the answers carefully and corrected your code. These three answer include all you need to fix your code to work. – user3078414 Jul 16 '16 at 21:24