在Objective-C中初始化一个结构体数组

4
我已经阅读了一段时间,但我不确定是否找到了一个好的答案。
我正在尝试设置一个包含92个结构体的数组。它是固定长度的,因此不会改变,实际上就像一个查找表。我认为最好的方法是首先使用 calloc 分配内存,然后加载数据。
但是在阅读一些内容后,我发现很多人直接分配内存而没有使用 calloc 或 malloc ,像这样:
 myStruct myData[92] = { {1,2}, {3,4}, ....};

我的第一个问题是是否更好地动态分配内存?我理解这是更好的解决方案,特别是如果数据不一定会一直使用。

我的第二个问题与初始化数据有关。我曾经读到可以使用 ... = {....}; 初始化结构体,但编译器不接受这种方式。

以下是我目前的代码:

typedef struct {
    int a;
    int b;
} myStruct;

@implementation MyClass

    static myStruct *myData;

    -(id) init {
         // ...

         myData = (myStruct *) calloc(92, sizeof(myStruct));
         myData[0] = {1,2}; // <=== Error ! Compiler says "Expected expression!"

         // ...

2
myData[0]=...是一种赋值操作,而不是初始化。不幸的是,在赋值操作中不允许使用初始化语法。 - Vaughn Cato
2
为什么要使用动态分配,而静态分配也是可行的呢?static myStruct myData[92] - user406009
1
这是我正在尝试理解的事情之一。我认为对于未知的事物,动态更好,而静态适用于固定的事物。因此,即使我的初始代码相对较大,但应该将其从动态改为静态? - drekka
3个回答

5

你的代码看起来像Objective-C,是这样吗?

如果你知道数组中有多少个元素(并且它是一个合理的处理器和操作系统),明确定义它总是更简单的。

每当你动态分配一个数组时,你需要防范一些意外情况发生,这会让代码难以理解。

如果它真的是一个查找表,并且所有的值都在编译时已知,你可以直接初始化它:

struct {
    int a;
    int b;
} myStructDate[92] = { {1, 2}, {3, 4}, ... {181, 182}, {183, 184} };

1
如果这些值是常量,将整个数组标记为“const”,它很可能会被添加到程序的只读“text”部分。 - Jonathan Leffler

3
关于问题1:静态分配数组应该没问题。 数组将存储在二进制数据部分中,将加载到进程的虚拟内存中,并在必要时由操作系统交换出来,就像您的进程正在使用的任何其他内存一样。访问数据时还可以节省时间,因为您不需要分配和初始化它。
关于问题2:至少gcc不喜欢这样初始化数组元素。但是您可以使用临时变量作弊:
myStruct s = {1,2};
myData[0] = s;

我不太确定标准在这方面说了什么。


2

因为这不是初始化,所以您需要进行赋值操作。

myData[0].a = 1;
myData[0].b = 2;

当你像这个例子一样初始化时,可以使用{}初始化,并设置数组。这有点浪费,因为如果使用上述方法,不需要临时变量。

myStruct temp = {1,2};
myStruct* myData = (myStruct *) calloc(92, sizeof(myStruct));
myData[0] = temp;

关于何时在堆上分配内存(通过malloc / calloc),一个好的经验法则是:如果需要在函数外使用它,则应该这样做。否则,您应该使用本地变量在堆栈上分配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接