Thread: Array of struct as function parameter

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    5

    Array of struct as function parameter

    Hi all.
    First of all, I speak french so you might see some french comments in my code, just don't pay attention to it.

    I'm having some trouble with a program of mine I'm trying to create.

    I have an array of struct having each some nested struct inside. Code of the structs definition (I really don't think there is any problem in this code yet):
    Code:
    //ncorps_definitions.h	
    #include<stdio.h>
    #include<stdlib.h>
    #include <math.h>
    #include <time.h>
    
    #define square(a) ((a)*(a))
    //#define min(a, b) ((a) < (b) ? (a) : (b))
    //#define max(a, b) ((a) < (b) ? (b) : (a))
    
    #define N 100		//nombres de particule dans la simulation
    #define CONDINIT 1	//chois des conditions initial parmis les différents presets (1: sphere uniforme avec acc=0 et vit=0, 2: coquille etc..
    #define TI 0		//temps initial
    #define TF 100		//temps final
    #define DELTA 10		//coefficient du pas de temps
    #define EPSILON 0.06	//longueur d'adoucissement pour 10 000 particules (à calculer dans les conditions initiales éventuellement)
    #define NOUT 1		//fréquence des ouputs
    #define SIGMA 0.2
    		
    
    
    typedef struct 
    {
    	double x;
    	double y;
    	double z;
    }Dimension;
    
    typedef struct	//décrit une particule
    {
    	double m;	//masse de la particule, pourra être négative ou positive
    	Dimension a;	//accélération des particules
    	Dimension v;	//vitesse des particules au début du pas de temps
    	Dimension vm;	//vitesse des particules au milieu du pas de temps
    	Dimension r;	//position des particules au début du pas de temps
    	Dimension rm;	//position des particules au milieu du pas de temps
    }Point;
    
    typedef struct
    {
    	Point aP[N];
    }allPoint;
    I have a main which declare this struct (it is called "sys") and then pass a pointer to this struct to various function:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    #include "ncorps_fonctions.h"
    
    int main(void)
    {
    	//déclaration des variables              ATENTION: remplacer potentiellement les valeurs par quelque chose de mieu et remplacer p-e les float par des double
    	allPoint sys;		//un array de structure contenant tout les points du système ainsi que toute leur propriété
    	FILE * pOutput; // pointeur sur le fichier d'output
    	double t;		//temps
    	double tOld;		//temps précédent
    	long int istep;	//nombre de cycle
    	double dt = 10; //pas de temps 
    	long int i = 0;
    
    	//chargement des conditions initiales des particules
    	conditionsInitiales(&sys);
    	
    	//ouverture du fichier d'output
    	pOutput = fopen("ncorps.output","w");
    	//évolution du système
    	t = TI;
    	istep = 0;
    	do {
    	
    		//1: Calcul les accélérations
    		accelerationsCalcul(&(sys.aP->r), &(sys.aP->a), &(sys.aP->m));
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //PROBLEME INSIDE THIS FUNCTION HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    .
    .
    .
    My program crash when it tries to do the function. So here are details of the function.
    header of the functions:
    Code:
    //ncorps_fonctions.h	
    #include "ncorps_definitions.h"
    
    /*****************************************************************************
    Description: cette fonction initialise les particules (via leur structure de type Point)
    *****************************************************************************/
    void conditionsInitiales(allPoint *pt);
    
    /*****************************************************************************
    Description: cette fonction calcul la nouvelle accélération de chaque particule selon leur position
    *****************************************************************************/
    void accelerationsCalcul(Dimension (*r)[N], Dimension (*a)[N], double (*m)[N]);
    
    /*****************************************************************************
    Description: cette fonction calcul la valeur du nouveau pas de temps et la retourne
    *****************************************************************************/
    double pasDeTemps(Dimension (*v)[N], Dimension (*a)[N]);
    The functions themself (You don't need to understand it all!!! see below where it crash exactly):

    Code:
    //ncorps_functions.c
    #include "ncorps_fonctions.h"
    
    /*****************************************************************************
    Description: cette fonction initialise les particules (via leur structure de type Point)
    *****************************************************************************/
    void conditionsInitiales(allPoint* pt)
    {
    	//variables
    	long int i = 0;
    	switch(CONDINIT)
    	{
    		case 1:	//sphere uniforme avec acc=0, vit=0 et masses à moitier négative
    			{
    				srand ( time(NULL) );	//initialisation de rand
    				
    				//ajouter éventuellement un paramètre  scale dans cette fonction (le scale sera calculer dans le main au début et sera fonction de ce qui est dit dans les notes de cours)
    				for (i = 0; i < N; i++)	
    				{	
    					//accélérations
    					pt->aP[i].a.x = 0;
    					pt->aP[i].a.y = 0;	
    					pt->aP[i].a.z = 0;
    					
    					//vitesses
    					pt->aP[i].v.x = rand() / (float) RAND_MAX * 2 - 1;
    					pt->aP[i].v.y = rand() / (float) RAND_MAX * 2 - 1;
    					pt->aP[i].v.z = rand() / (float) RAND_MAX * 2 - 1;
    					
    					//positions
    					pt->aP[i].r.x = rand() / (float) RAND_MAX * 2 - 1;
    					pt->aP[i].r.y = rand() / (float) RAND_MAX * 2 - 1;
    					pt->aP[i].r.z = rand() / (float) RAND_MAX * 2 - 1;
    					
    					//masses
    					pt->aP[i].m = rand() / (float) RAND_MAX * 2 - 1;
    				}			
    			}
    			break;
    			
    		case 2:	//coquille avec acc=0 et vit=0.. etc..
    			{
    				
    			}
    			break;
    	}
    }
    
    /*****************************************************************************
    Description: cette fonction calcul la nouvelle accélération de chaque particule selon leur position
    *****************************************************************************/
    void accelerationsCalcul(Dimension (*r)[N], Dimension (*a)[N], double (*m)[N])
    {
    	//déclaration des variables
    	long int i, j = 0;
    	double xi,yi,zi,xj,yj,zj,denom,cmi,cmj,dx,dy,dz,r2;
    	xi=yi=zi=xj=yj=zj=denom=cmi=cmj=dx=dy=dz=r2 = 0;
    
    	//initialise les accélérations à 0
    	for (i = 0; i < N; i++)
    	{
    		a[i]->x = 0;
    		a[i]->y = 0;
    		a[i]->z = 0;
    	}
    	
    	//calcul la force entre toute les paires de particules
    	for (i =0; i < (N - 1); i++)
    	{
    		xi = r[i]->x;
    		yi = r[i]->y;
    		zi = r[i]->z;
    		
    		for (j = (i + 1); j < N; j++)
    		{
    			xj = r[j]->x;
    			yj = r[j]->y;
    			zj = r[j]->z;
    			
    			dx = xi - xj;
    			dy = yi - yj;
    			dz = zi - zj;
    			
    			r2 = square(dx) + square(dy) + square(dz);
    			denom = pow((r2 + square(EPSILON)),(15.0 / 10.0));
    			
    			cmj = *m[j] / denom;
    			cmi = *m[i] / denom;
    			
    			a[i]->x = a[i]->x - cmj*dx;
    			a[i]->y = a[i]->y - cmj*dy;
    			a[i]->z = a[i]->z - cmj*dz;
    			
    			a[j]->x = a[j]->x - cmi*dx;
    			a[j]->y = a[j]->y - cmi*dy;
    			a[j]->z = a[j]->z - cmi*dz;
    		}
    	}
    }

    The program crash exactly at this line into the function "accelerationsCalcul":
    Code:
    a[i]->x = 0;
    but my program seems to work fine when it calls the first function "conditionsInitiales"

    so this tells me there is something wrong when I declared the function or when I tried to pass the struct as a pointer to the function.

    so to kind of make it short, I think there is a prolem somewhere in those lines:

    function header
    Code:
    void accelerationsCalcul(Dimension (*r)[N], Dimension (*a)[N], double (*m)[N]);
    or actual function code
    Code:
    void accelerationsCalcul(Dimension (*r)[N], Dimension (*a)[N], double (*m)[N])
    or function into main.c
    Code:
    accelerationsCalcul(&(sys.aP->r), &(sys.aP->a), &(sys.aP->m));
    What did I do wrong in this process? I know how to usualy pass Struct as a function parameter, but I'm totaly lost when it comes to array of structs and even more when i have to pass only part of an array of struct (
    Code:
    &(sys.aP->r)
    )

    thank you very much (going to bed now o.O, I will answer anything tomorrow..)

  2. #2
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Please describe what you think this is:
    Code:
    Dimension (*r)[N]

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    There's a disconnect between the function call arguments and the parameters in the definition.
    Code:
    accelerationsCalcul(&(sys.aP->r), &(sys.aP->a), &(sys.aP->m));   /* function call in main() */
    Above arguments are all pointers to objects of type Dimension(double) but in the function header
    Code:
    void accelerationsCalcul(Dimension (*r)[N], Dimension (*a)[N], double (*m)[N])
    each parameter is a pointer to an array of N elements of type Dimension(double), so change the function header to
    Code:
    void accelerationsCalcul(Dimension *r, Dimension *a,  double *m)

  4. #4
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Considering he is using a, r and m as arrays, I don' think your suggestion is going to help him lots.

    Personally, I think that he should just rewrite accelerationsCalcul() as below and work from there.
    Code:
    accelerationsCalcul( allPoint *obj );

  5. #5
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by msh View Post
    Considering he is using a, r and m as arrays, I don' think your suggestion is going to help him lots.
    Well this is the case of the op proposes and the compiler disposes.
    Where in the code are the variables a, r, and m defined as arrays?
    They're just simple objects of type Dimension (a / r) and double (m).
    Quote Originally Posted by msh View Post
    Personally, I think that he should just rewrite accelerationsCalcul() as below and work from there.
    Code:
    accelerationsCalcul( allPoint *obj );
    Yep! that'd work as long as the object references are kept in order.

  6. #6
    Registered User
    Join Date
    Jun 2010
    Posts
    5
    Quote Originally Posted by msh View Post
    Please describe what you think this is:
    Code:
    Dimension (*r)[N]
    I see this as an array of N pointers of type "Dimension"

    Quote Originally Posted by itCbitC
    each parameter is a pointer to an array of N elements of type Dimension(double), so change the function header to
    Code:
    void accelerationsCalcul(Dimension *r, Dimension *a,  double *m)
    The reason i used arrays for r, a and m, is that those function arguments are kinda arrays themself. Because aP is an array, that mean the function should receive 3 x N structs adresses. So i was trying to capture all those array with pointers of this kind
    Code:
    Dimension (*r)[N]
    I think i will take msh suggestion and rewrite the function with a complete allPoint struct, but let me tell you first why i tried to avoid it in the first place. The time to run the whole program scale has N^2, and I'm looking to make N as big as my computer can handle (I hope to one day reach N =100 000, but right now I can't even reach N=10 000 without stack overflow, wich I find weird since it looks like a pretty small number to me...). The function "accelerationsCalcul" will be called a couple thousands of time so I wanted to make it as quick as possible and supply it will only what it needed. So my question is: Is passing an allPoint array to the function really slower than passing just specific part of the array?

    I might add that the majority of computer calculus time will be spent inside the function "accelerationsCalcul" (wich I hope to make it run on my 3d Card with CUDA as the ultimate goal of this project after I understand how to make it run great on hte cpu first)

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by rotger
    I see this as an array of N pointers of type "Dimension"
    As itCbitC stated in post #3, r is actually a pointer to an array of N Dimension objects.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Quote Originally Posted by rotger View Post
    Is passing an allPoint array to the function really slower than passing just specific part of the array?
    With what I suggested, you wouldn't be passing an array to the function; you would be passing the address of your sys structure that contains the array of Point structures. This is called "passing by reference". The function doesn't get a copy of an object, just it's address, and then modifies the structure it finds at this address.


    Or did I misunderstand your question?

  9. #9
    Registered User
    Join Date
    Jun 2010
    Posts
    5
    msh: My bad, I badly worded my sentence. And now that you say it, it makes perfect sense that passing an adress as function parameter is as fast regardless of if I use it to point to a big struct or a smaller one.

    ok thank you all, I should be able to work out something that work.

  10. #10
    Novice
    Join Date
    Jul 2009
    Posts
    568


    Another thing that you should consider if you want to work with a large number of objects is allocating your memory dynamically.

  11. #11
    Registered User
    Join Date
    Jun 2010
    Posts
    5
    Without entering into too much details, is dynamic memory allocation useful when the size of "N" is known before launching the program and I know it won't change?
    Or dynamic allocation will kinda of make a better use of my available memory?
    And when we talk about dynamic allocation, are we talking about malloc, calloc and realloc? or some kind of linked list? (maybe this question doesn't even make sense.. I just don't know a lot about dynamic memory allocation apart that it exist, I will go read about it if that is needed for the program)

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    No, if you know the size of your data set will never change during run time, dynamic memory allocation and linked lists are not necessary. As a matter of fact, they would make your coding job much harder. You did well enough to define N as your array size and code everything in terms of that.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by rotger
    Without entering into too much details, is dynamic memory allocation useful when the size of "N" is known before launching the program and I know it won't change?
    Yes, because there tends to be a much lower limit to space on the stack than the heap. That said, you could make the fixed size array global to avoid the limits of the stack... but global variables should normally be avoided.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Replies: 10
    Last Post: 05-18-2006, 11:23 PM
  4. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  5. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM