如何在 C 中存储自定义对象(结构)?

How to store custom objects (struct) in C?

我想知道如何在 C 中存储自定义对象(不是它们的指针)。我创建了一个名为 Node

的自定义结构
#define MAXQ 100

typedef struct {
  int state[MAXQ];
  int height;
} Node;

(有效)并且我想将这些节点中的一些存储在一个容器中(不使用指针,因为它们没有存储在其他地方)以便我以后可以访问它们。

互联网似乎建议类似 calloc() 所以我最后的尝试是在 this example 之后制作一个容器 Neighbors,其中 numNeighbors 只是一个整数:

Node Neighbors = (Node*)calloc(numNeighbors, sizeof(Node));

在编译时,我从这行中得到一个错误,说
initializing 'Node' with an expression of incompatible type 'void *'

在我引用这个容器的地方(如 Neighbors[i])我得到了
的错误 subscripted value is not an array, pointer, or vector

因为我被 Python 宠坏了,我不知道我的语法是否完全错误(它应该告诉你一些我在搜索了大量教程后仍然不在那里的东西, malloc()calloc() 等上的文档和 Whosebugs),或者如果我使用完全错误的方法来存储自定义对象(在互联网上搜索 "store custom objects in C" 会得到与处理 iOS 和 C# 所以我真的很感激一些帮助)。

编辑:感谢大家的指点,终于编译无误!

您可以使用自定义结构创建常规数组:

Node Neighbors[10];

然后您可以像引用任何其他数组一样引用它们,例如:

Neighbors[3].height = 10;

如果您的 C 实现支持 C.1999 风格的 VLA,只需定义您的数组。

Node Neighbors[numNeighbors];

(请注意,VLA 没有错误报告机制。分配失败会导致未定义的行为,这可能表现为崩溃。)

否则,您将需要动态分配。 calloc 是合适的,但它 returns 代表连续分配的指针。

Node *Neighbors = calloc(numNeighbors, sizeof(*Neighbors));

注意,在用 C 编程时不要强制转换 malloc/calloc/realloc 的结果。这不是必需的,在最坏的情况下,可以掩盖致命的错误错误。

malloc和calloc是动态分配的,需要指针变量。我看不出有任何理由让您使用动态分配。只要定义一个常规数组,直到你有理由不这样做。

#define MAXQ 100
#define NUM_NEIGHBORS 50

typedef struct {
  int state[MAXQ];
  int height;
} Node;

int main(void)
{
  Node Neighbors[NUM_NEIGHBORS];

  Neighbors[0].state[0] = 0;
  Neighbors[0].height = 1;
}

这里NUM_NEIGHBORS需要是一个常量。 (因此是静态的)如果你希望它是可变的或动态的,那么你需要动态分配,并且不可避免地需要指针:

#define MAXQ 100

typedef struct {
  int state[MAXQ];
  int height;
} Node;

int main(void)
{
  int numNeighbors = 50;
  Node *Neighbors;

  Neighbors = (Node*)calloc(numNeighbors, sizeof(Node));
  Neighbors[0].state[0] = 0;
  Neighbors[0].height = 1;
}

I want to store a few of these Nodes in a container (without using pointers, since they are not stored elsewhere) so I can access them later.

如果您在编译时知道它们的数量(或者至少是一个合理的最大值);然后你可以创建一个堆栈分配对象的数组。例如,假设您最多可以处理 10 个对象:

#define MAX_NODES 10

Node nodes[MAX_NODES];
int number_nodes = 0;

然后当您添加一个对象时,您会保持同步 number_nodes(以便您知道将下一个对象放在哪里)。从技术上讲,您将始终拥有 10 个,但您只使用那些 want/need。删除对象是类似的,但如果你想删除中间的一些则更复杂。

但是,如果您不知道您将拥有多少(也不知道最大值);或者即使您知道,但它们太多而无法放入堆栈;然后你被迫使用堆(通常使用 malloc() and free()):

int number_nodes; // unknown until runtime or too big
Node * nodes = malloc(sizeof(Node) * number_nodes);
...
free(nodes);

无论如何,您将在动态分配内存的情况下使用指针,而且很可能在堆栈情况下也是如此。

Python 正在幕后隐藏并为您表演所有这些舞蹈——您可能已经意识到这一点非常有用且节省时间,只要您不需要对其进行精确控制(阅读:性能)。