Amndeep7
Amndeep7

Reputation: 2091

How do you make an array of structs in C?

I'm trying to make an array of structs where each struct represents a celestial body.

I don't have that much experience with structs, which is why I decided to try to use them instead of a whole bunch of arrays. However, I keep on running into numerous different errors. I've tried to implement the techniques that I've seen on various threads and on Stack Overflow (such as Array of structs in C and Initialize array of structs in C), however not all of them were applicable.

Further information for those who have read this far: I don't need any of this to be dynamic, I know/define the size of everything beforehand. I also need this to be a global array as I'm accessing this in several different methods which have defined arguments (i.e., GLUT methods).

This is how I'm defining the struct in my header:

struct body
{
    double p[3]; // Position
    double v[3]; // Velocity
    double a[3]; // Acceleration
    double radius;
    double mass;
};

I have a list of other global variables that I'm defining before I define the interior of the struct, and one of those is the array of this struct (basically, if I'm being too unclear in my fogged speak, the line below is above the stuff above):

struct body bodies[n];

Just so you know, n is something that I've legitimately defined (i.e. #define n 1).

I use this array in several different methods, but the easiest and least space consuming one is a simplified form of my main. Here I initialize all of the variables in each of the structs, just to set the variables for certain before I modify them in some way:

int a, b;
for(a = 0; a < n; a++)
{
    for(b = 0; b < 3; b++)
    {
        bodies[a].p[b] = 0;
        bodies[a].v[b] = 0;
        bodies[a].a[b] = 0;
    }
    bodies[a].mass = 0;
    bodies[a].radius = 1.0;
}

The current error that I'm facing is nbody.c:32:13: error: array type has incomplete element type where line 32 is where I'm making the array of the structs.

One last clarification: By header I mean the space above int main(void), but in the same *.c file.

Upvotes: 141

Views: 775752

Answers (10)

Helping Bean
Helping Bean

Reputation: 147

Solution using pointers:

#include <stdio.h>
#include <stdlib.h>

#define n 3

struct body
{
    double p[3]; // Position
    double v[3]; // Velocity
    double a[3]; // Acceleration
    double radius;
    double *mass;
};


int main()
{
    struct body *bodies = (struct body*)malloc(n*sizeof(struct body));
    int a, b;
    for(a = 0; a < n; a++)
    {
        for(b = 0; b < 3; b++)
        {
            bodies[a].p[b] = 0;
            bodies[a].v[b] = 0;
            bodies[a].a[b] = 0;
        }
        bodies[a].mass = 0;
        bodies[a].radius = 1.0;
    }


    free(bodies);
    return 0;
}

Upvotes: 2

Phoenixcomm
Phoenixcomm

Reputation: 45

I don't know who came up with this one but. YES, you can build structs containing other structs! case in point work on a flight sim requires knowing start, finish, and current locations (Latitude and Longitude). An example that I use:

struct DM {
   int degrees;
   float minutes;
   char hemi; };

Now I need two of them one for Lat and the other for Lon so;

struct DM Lat;
struct DM Lon;

Now let's put it all together and call it Position

struct Position {
    struct DM Lat;
    struct DM Lon; } Current, Start, Finish;

and to access start I will use Addison, Texas // Addison: 32-58.113333N 096-50.186667W

Finish.Lon.degrees = 32;
Finish.Lon.minutes = 58.113333;
Finish.Lon.hemi    = 'N';
Finish.Lat.degrees = 96;
Finish.Lat.minutes = 0.186667;
Finish.Lat.hemi    = 'W'; 

Fins ps Now what's all this crud about not making a struct within a struct??

Upvotes: -1

Christakitos
Christakitos

Reputation: 144

I think you could write it this way too. I am also a student, so I understand your struggle.

#include <stdio.h>
#define n 3

struct {
    double p[3]; // Position
    double v[3]; // Velocity
    double a[3]; // Acceleration
    double radius;
    double mass;
} bodies[n];

Upvotes: 12

nims
nims

Reputation: 3871

Use:

#include<stdio.h>

#define n 3

struct body
{
    double p[3]; // Position
    double v[3]; // Velocity
    double a[3]; // Acceleration
    double radius;
    double mass;
};

struct body bodies[n];

int main()
{
    int a, b;
    for(a = 0; a < n; a++)
    {
        for(b = 0; b < 3; b++)
        {
            bodies[a].p[b] = 0;
            bodies[a].v[b] = 0;
            bodies[a].a[b] = 0;
        }
        bodies[a].mass = 0;
        bodies[a].radius = 1.0;
    }

    return 0;
}

This works fine. Your question was not very clear by the way, so match the layout of your source code with the above.

Upvotes: 147

vrk001
vrk001

Reputation: 335

Move

struct body bodies[n];

to after

struct body
{
    double p[3]; // Position
    double v[3]; // Velocity
    double a[3]; // Acceleration
    double radius;
    double mass;
};

The rest all looks fine.

Upvotes: 8

Toby Speight
Toby Speight

Reputation: 30709

Attempting to reconstruct your program, I get

struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

#define n 9

struct body bodies[n];

int main(void)
{
    int a, b;
    for (a = 0; a < n; a++) {
        for (b = 0; b < 3; b++) {
            bodies[a].p[b] = 0;
            bodies[a].v[b] = 0;
            bodies[a].a[b] = 0;
        }
        bodies[a].mass = 0;
        bodies[a].radius = 1.0;
    }
}

This compiles without error using gcc-11 -std=c17 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion -Wstrict-prototypes -fanalyzer, so it's unclear why you have a problem.

However, we still have opportunity to simplify it by using a constant struct body for initialisation:

int main(void)
{
    static const struct body default_body =
        { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, 0.0, 1.0 };

    for (unsigned i = 0;  i < n;  ++i) {
        bodies[i] = default_body;
    }
}

Upvotes: 0

Yanjan. Kaf.
Yanjan. Kaf.

Reputation: 1725

You can do it in a same manner as you create the array of numbers but wrap the element's values in braces like this ->

struct Wrestler studs[count] = {
        {"John", "Cena"},
        {"The", "Undertaker"},
        {"The", "Big Show"},
        {"The", "Rock"},
        {"Triple", "H"},
        {"Scott", "Hall"},
        {"Roman", "Reings"},
        {"Dean", "Ambrose"}};

Here is full code

#include <stdio.h>

struct Wrestler
{
    char firstName[20];
    char secondName[20];
};

void pIntro(struct Wrestler *s)
{
    printf("Hi, I am %s %s.\n", s->firstName, s->secondName);
};

int main(int argc, char const *argv[])
{
#define count 8
    struct Wrestler studs[count] = {
        {"John", "Cena"},
        {"The", "Undertaker"},
        {"The", "Big Show"},
        {"The", "Rock"},
        {"Triple", "H"},
        {"Scott", "Hall"},
        {"Roman", "Reings"},
        {"Dean", "Ambrose"}};

    for (int i = 0; i < count; i++)
    {
        pIntro(&(studs[i]));
    }

    return 0;
}


Upvotes: 3

Abdel Aleem
Abdel Aleem

Reputation: 747

Another way of initializing an array of structs is to initialize the array members explicitly. This approach is useful and simple if there aren't too many struct and array members.

Use the typedef specifier to avoid re-using the struct statement everytime you declare a struct variable:

typedef struct
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
}Body;

Then declare your array of structs. Initialization of each element goes along with the declaration:

Body bodies[n] = {{{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}, 
                  {{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}, 
                  {{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}};

To repeat, this is a rather simple and straightforward solution if you don't have too many array elements and large struct members and if you, as you stated, are not interested in a more dynamic approach. This approach can also be useful if the struct members are initialized with named enum-variables (and not just numbers like the example above) whereby it gives the code-reader a better overview of the purpose and function of a structure and its members in certain applications.

Upvotes: 24

Dounchan
Dounchan

Reputation: 349

So to put it all together by using malloc():

int main(int argc, char** argv) {
    typedef struct{
        char* firstName;
        char* lastName;
        int day;
        int month;
        int year;

    }STUDENT;

    int numStudents=3;
    int x;
    STUDENT* students = malloc(numStudents * sizeof *students);
    for (x = 0; x < numStudents; x++){
        students[x].firstName=(char*)malloc(sizeof(char*));
        scanf("%s",students[x].firstName);
        students[x].lastName=(char*)malloc(sizeof(char*));
        scanf("%s",students[x].lastName);
        scanf("%d",&students[x].day);
        scanf("%d",&students[x].month);
        scanf("%d",&students[x].year);
    }

    for (x = 0; x < numStudents; x++)
        printf("first name: %s, surname: %s, day: %d, month: %d, year: %d\n",students[x].firstName,students[x].lastName,students[x].day,students[x].month,students[x].year);

    return (EXIT_SUCCESS);
}

Upvotes: 23

David
David

Reputation: 129

That error means that the compiler is not able to find the definition of the type of your struct before the declaration of the array of structs, since you're saying you have the definition of the struct in a header file and the error is in nbody.c then you should check if you're including correctly the header file. Check your #include's and make sure the definition of the struct is done before declaring any variable of that type.

Upvotes: 1

Related Questions