【问题标题】:How do you make an array of structs in C?如何在 C 中创建一个结构数组?
【发布时间】:2012-05-15 03:17:41
【问题描述】:

我正在尝试创建一个结构数组,其中每个结构代表一个天体。

我对结构没有太多经验,这就是为什么我决定尝试使用它们而不是一大堆数组。但是,我不断遇到许多不同的错误。我尝试实现我在各种线程和 StackOverflow 上看到的技术(例如 Array of structs in CC - initialize array of structs),但并非所有技术都适用。

对于已经阅读本文的人的更多信息:我不需要任何动态,我事先知道/定义了所有内容的大小。我还需要将它作为一个全局数组,因为我在几种不同的方法中访问它,这些方法已经定义了参数(即 GLUT 方法)。

这就是我在标题中定义结构的方式:

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

在我定义结构的内部之前,我有一个我正在定义的其他全局变量的列表,其中一个是这个结构的数组(基本上,如果我在我的模糊发言中太不清楚,下面的行在上面的东西上面):

struct body bodies[n];

您知道,n 是我合法定义的东西(即#define n 1)。

我在几种不同的方法中使用这个数组,但最简单且占用空间最少的一种是我的 main.js 的简化形式。这里我初始化了每个结构中的所有变量,只是为了在我以某种方式修改它们之前设置变量:

  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;
 }

我面临的当前错误是nbody.c:32:13: error: array type has incomplete element type,其中第 32 行是我制作结构数组的位置。

最后澄清一下,标题是指int main(void) 上方的空格,但在同一个*.c 文件中。

【问题讨论】:

  • 嗯,它对我来说很好用。你不是在声明struct body {}之前声明struct body bodies[n];吗?
  • 请注意,当数组的大小超过系统上程序的堆栈大小时(这完全超出了程序员的控制范围),使用可变长度数组通常会导致神秘的错误或崩溃。最好使用 malloc() 处理这种事情。
  • @adrian 我认为因为它是 #defined 值,所以它不是可变的。它将与struct body bodies[1] 相同,或者与n 的值相同。
  • @RedwolfPrograms 啊抱歉,我没有考虑到这一点。作为记录,如果n 是一个可以在编译时确定的常量,那么您可能是安全的。

标签: c arrays struct


【解决方案1】:

移动

struct body bodies[n];

到之后

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

一切看起来都很好。

【讨论】:

    【解决方案2】:
    #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;
    }
    

    这很好用。顺便说一下,你的问题不是很清楚,所以将源代码的布局与上面的匹配。

    【讨论】:

    • 另外,我有一个关于结构类型声明和实际创建它的实例之间的位置的问题 - 我有一个不同的结构,我在下面定义了 的内容 我第一次创建它的实例(这次只是一个,不是数组),那么为什么这没有产生大量的错误呢?它工作得很好,这让我认为我制作数组的尝试应该也能奏效,但这次它没有奏效。另外,谢谢你的回答,它成功了。
    • 嗨,.... 59 个赞?我没有看到结构数组,我只看到来自被击中的变量数组...
    【解决方案3】:

    该错误意味着编译器在声明结构数组之前无法找到结构类型的定义,因为您说您在头文件中具有结构的定义并且错误在nbody.c 中,那么你应该检查你是否正确地包含了头文件。 检查您的 #include 并确保在声明该类型的任何变量之前完成了结构的定义。

    【讨论】:

    • 我怀疑 OP 意味着头文件作为头文件,正如他所写的,“下面的行在上面的东西之上”在他的 nbody.c 文件中的结构数组声明之前。让我们等他醒来,解开疑惑。
    • @nims 是正确的,我的标题是指main 语句上方的区域。
    【解决方案4】:

    所以用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);
    }
    

    【讨论】:

    • 你的 malloc 行应该有 numStudents * sizeof(STUDENT) 吗?
    • @Todd 最好不要。 sizeof *students 是一回事,如果 STUDENT 发生变化也不会错。
    • @trentcl 他为 {numStudents} 个指针分配了内存。不是结构,而是指针。指针大小通常为 4 字节,同时结构的大小为 20 字节。 20 个字节是可被 4 整除的数字,因此不需要填充,并且结构存储在从起始地址开始的每 20 个字节上。它之所以有效,是因为您只为一种特定情况分配内存。否则其他 malloc 可能会覆盖您的结构的内存,因为它没有分配并且您已经溢出了您的学生内存。
    • @JohnSmith 你错了;再读一遍。 sizeof *students指向的内容 的大小,即sizeof(STUDENT),而不是sizeof(STUDENT*)。您正在犯ptr = malloc(num * sizeof *ptr) 成语应该防止的确切错误。检查它here(请注意,与大多数现代 PC 一样,服务器具有 8 字节指针,因此大小为 8 和 32 而不是 4 和 20)。
    • @trentcl 谢谢你的解释。我对在它自己的初始化中取消引用指针的语法感到困惑。我想说这有点令人困惑,但绝对是更紧凑的解决方案。
    【解决方案5】:

    我想你也可以这样写。我也是一名学生,所以我理解你的挣扎。回复有点晚,但还好。

    #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];
    

    【讨论】:

      【解决方案6】:

      使用指针的解决方案:

      #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;
           }
      
          return 0;
      }
      

      【讨论】:

        【解决方案7】:

        另一种初始化结构数组的方法是显式初始化数组成员。如果没有太多的结构和数组成员,这种方法非常有用且简单。

        使用typedef 说明符避免在每次声明结构变量时重复使用struct 语句:

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

        然后声明你的结构数组。每个元素的初始化都伴随着声明:

        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}};
        

        重复一遍,如果您没有太多的数组元素和大型结构成员,并且如您所说,您对更动态的方法不感兴趣,这是一个相当简单直接的解决方案。如果结构成员使用命名的枚举变量(而不仅仅是上面示例中的数字)进行初始化,这种方法也很有用,这样它可以让代码阅读者更好地了解结构及其成员的目的和功能。应用程序。

        【讨论】:

        • 喜欢这个!好简单的答案?
        猜你喜欢
        • 2011-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-24
        相关资源
        最近更新 更多