8

我想动态分配一个 C 结构:

typedef struct {
    short *offset;
    char *values;
} swc;

'offset' 和 'values' 都应该是数组,但它们的大小直到运行时才知道。

如何为我的结构和结构的数组动态分配内存?

4

13 回答 13

21
swc *a = (swc*)malloc(sizeof(swc));
a->offset = (short*)malloc(sizeof(short)*n);
a->values = (char*)malloc(sizeof(char)*n);

其中 n = 每个数组中的项目数,a 是新分配的数据结构的地址。不要忘记在 free()'ing a 之前释放() 偏移量和值。

于 2009-12-30T12:16:39.790 回答
11

在 C 中:

swc *s = malloc(sizeof *s); // assuming you're creating a single instance of swc
if (s)
{
  s->offset = malloc(sizeof *(s->offset) * number_of_offset_elements);
  s->values = malloc(sizeof *(s->values) * number_of_value_elements);
}

在 C++ 中:

try
{
  swc *s = new swc;
  s->offset = new short[number_of_offset_elements];
  s->values = new char[number_of_value_elements];
}
catch(...)
{
   ...
}

请注意,在 C++ 中,使用向量而不是动态分配的缓冲区可能会更好:

struct swc 
{
  std::vector<short> offset;
  std::vector<char> values;
};

swc *a = new swc;

问题:值应该是单个字符数组还是字符串数组?那会改变一些事情。

编辑

我想得越多,我对 C++ 的答案就越不满意;在 C++ 中做这种事情的正确方法(假设你需要动态分配的缓冲区而不是向量,你可能不需要)是在结构类型中作为构造函数的一部分执行偏移量和值的内存分配,并在结构实例被销毁(通过 adelete或超出范围)时让析构函数释放这些元素。

struct swc
{
  swc(size_t numOffset = SOME_DEFAULT_VALUE, 
      size_t numValues = SOME_OTHER_DEFAULT_VALUE)
  {
    m_offset = new short[numOffset];
    m_values = new char[numValues];
  }

  ~swc()
  {
    delete[] m_offset;
    delete[] m_values;
  }

  short *m_offset;
  char  *m_values;
};

void foo(void)
{
  swc *a = new swc(10,20); // m_offset and m_values allocated as 
                           // part of the constructor
  swc b;                   // uses default sizes for m_offset and m_values
  ...
  a->m_offset[0] = 1;
  a->m_values[0] = 'a';
  b.m_offset[0] = 2;
  b.m_values[0] = 'b';
  ...
  delete a; // handles freeing m_offset and m_values
            // b's members are deallocated when it goes out of scope
}
于 2009-12-30T14:33:22.007 回答
5

在 C 中:

typedef struct
{
    short *offset;
    char  *values;
} swc;

/// Pre-Condition:  None
/// Post-Condition: On failure will return NULL.
///                 On Success a valid pointer is returned where
///                 offset[0-n) and values[0-n) are legally de-refrancable.
///                 Ownership of this memory is returned to the caller who
///                 is responsible for destroying it via destroy_swc()
swc *create_swc(unsigned int size)
{
    swc *data    = (swc*)  malloc(sizeof(swc));
    if (data)
    {
        data->offset = (short*)malloc(sizeof(short)*n);
        data->values = (char*) malloc(sizeof(char) *n);
    }
    if ((data != NULL) && (size != 0) && ((data->offset == NULL) || (data->values == NULL)))
    {
        // Partially created object is dangerous and of no use.
        destroy_swc(data);
        data = NULL;
    }
    return data;
}
void destroy_swc(swc* data)
{
    free(data->offset);
    free(data->values);
    free(data);
}

在 C++ 中

struct swc
{
    std::vector<short>   offset;
    std::vector<char>    values;
    swc(unsigned int size)
        :offset(size)
        ,values(size)
    {}
};
于 2009-12-30T15:30:54.793 回答
5

你必须分开做。首先分配结构,然后为数组分配内存。

在 C 中:

swc *pSwc = malloc(sizeof(swc));
pSwc->offset = malloc(sizeof(short)*offsetArrayLength);
pSwc->values = malloc(valuesArrayLength);

在 C++ 中,你不应该做这样的事情。

于 2009-12-30T12:16:41.690 回答
4

您将需要一个函数来执行此操作。类似的东西(我的 C/C++ 生锈了)

swc* makeStruct(int offsetCount, int valuesCount) {
  swc *ans = new swc();
  ans->offset = new short[offsetCount];
  ans->values = new char[valuesCount];
  return ans;
}

myNewStruct = makeStruct(4, 20);

语法可能有点偏离,但这通常是您需要的。如果您使用的是 C++,那么您可能想要一个带有构造函数的类,该构造函数采用 2 个参数而不是 makeStruct 但做一些非常相似的事情。

于 2009-12-30T12:16:34.763 回答
3

在这里添加许多正确答案的一件事:您可以 malloc使用一个过大的结构来容纳最后一个成员中的可变大小的数组。

struct foo {
   short* offset;
   char values[0]
};

然后

struct *foo foo1 = malloc(sizeof(struct foo)+30); // takes advantage of sizeof(char)==1

values为数组中的 30 个对象腾出空间。你仍然需要做

foo1->offsets = malloc(30*sizeof(short));

如果您希望他们使用相同大小的数组。

我通常不会真正这样做(如果结构需要扩展,维护噩梦),但它是工具包中的一个工具。

[这里的代码c。您需要在 c++中转换malloc's (或更好地使用和 RAII 习语)]new

于 2009-12-30T14:41:39.630 回答
2
swc* a = malloc(sizeof(*a));
a->offset = calloc(n, sizeof(*(a->offset)));
a->values = calloc(n, sizeof(*(a->values)));

你不应该在 c 中强制转换 void* ...在 c++ 中你必须!

于 2009-12-30T13:57:51.247 回答
1

由于还没有人提到它,有时在一次分配中获取这块内存是很好的,所以你只需要在一件事情上调用 free() :

swc* AllocSWC(int items)
{
    int size = sizeof(swc); // for the struct itself
    size += (items * sizeof(short)); // for the array of shorts
    size += (items * sizeof(char)); // for the array of chars
    swc* p = (swc*)malloc(size);
    memset(p, 0, size);
    p->offset = (short*)((char*)swc + sizeof(swc)); // array of shorts begins immediately after the struct
    p->values = (char*)((char*)swc + sizeof(swc) + items * sizeof(short)); // array of chars begins immediately after the array of shorts
    return p;
}

当然,这有点难以阅读和维护(特别是如果您在首次分配数组后动态调整数组大小)。只是我在许多地方看到的另一种方法。

于 2009-12-30T16:30:51.267 回答
1

使用 malloc 函数或 calloc 动态分配内存。并在谷歌上搜索以获取示例。

The calloc function initializes allocated memory to zero.
于 2009-12-30T12:13:55.100 回答
1

Most of the answers are correct. I would like to add something that you haven't explicitly asked but might also be important.

C / C++ arrays don't store their own size in memory. Thus, unless you want offset and values to have compile-time defined values (and, in that case, it's better to use fixed-size arrays), you might want to store the sizes of both arrays in the struct.

typedef struct tagswc {
    short  *offset;
    char   *values;
    // EDIT: Changed int to size_t, thanks Chris Lutz!
    size_t offset_count;
    size_t values_count; // You don't need this one if values is a C string.
} swc;

DISCLAIMER: I might be wrong. For example, if all offsets of all swc instances have the same size, it would be better to store offset_count as a global member, not as a member of the struct. The same can be said about values and values_count. Also, if values is a C string, you don't need to store its size, but beware of Schlemiel the painter-like problems.

于 2009-12-30T15:51:27.887 回答
0

您想使用malloc来分配内存,并且可能还想使用 sizeof() 来分配正确的空间量。

就像是:
structVariable = (*swc) malloc(sizeof(swc));

应该做的伎俩。

于 2009-12-30T12:18:17.957 回答
0

除了上述之外,我想添加释放分配的内存如下。,

    typedef struct { 
    short *offset; 
    char *values; 
} swc;

swc* createStructure(int Count1, int Count2) { 
  swc *s1 = new swc(); 
  s1->offset = new short[Count1]; 
  s1->values = new char[Count2]; 
  return s1; 
} 

int _tmain(int argc, _TCHAR* argv[])
{
    swc *mystruct;
    mystruct = createStructure(11, 11);

    delete[] mystruct->offset;
    delete[] mystruct->values;
     delete mystruct;
    return 0;
}
于 2009-12-30T14:53:10.200 回答
0

**如果**您不会调整数组的大小,那么您只需调用malloc().

swc *new_swc (int m, int n) {
    swc *p;
    p = malloc (sizeof (*p) + m * sizeof (p->offset[0]) + n * sizeof (p->values[0]);
    p->offset = (short *) &p[1];
    p->values = (char *) &p->offset[m];
    return p;
}

然后,您只需调用free().

(一般来说,有对齐的考虑要考虑,但是对于一个短裤数组,后面跟着一个字符数组,你会没事的。)

于 2009-12-30T16:52:05.860 回答