Search code examples
objective-cdynamic-memory-allocation

How to use a dynamic C array inside a struct


I did extensive research before asking this question here, but I couldn't find an answer.

I have a simple struct that contains an array of another struct and the total:

typedef struct {
    int total;
    struct Struct1 arrayOfStructs[];
} Struct2;
Struct2 _myVar;  // the variable I need
  • arrayOfStructs[] should be a C array containing structs of type Struct1 (this syntax is not valid, because you need a constant value)
  • total is the count of the arrayOfStructs
  • (Struct1 is not relevant, it just contains some primitive data)

The problem is that I want this array to be dynamic. I want to be able to do this:

for (int i = 0; i < _myVar.total; i++) {
    NSLog(@"%d", _myVar.arrayOfStructs[i].index);
}

I tried the following:

typedef struct {
    int total;
    struct Struct1 *arrayOfStructs;  // USING A POINTER HERE
} Struct2;
Struct2 _myVar;  // the variable I need

and for adding values:

int total = ++_myVar.total;  // increase total count
_myVar.arrayOfStructs = realloc(_myVar.arrayOfStructs, total * sizeof(Struct1));
_myVar.arrayOfStructs[total - 1] = {1, 5.3};  // appending a new value in the array

The above code adds the value correctly, but after passing it into NSData and retrieving it, the array items are lost, and I end up with some bad pointers:

[NSData dataWithBytes:&_myVar length:sizeof(_myVar) + sizeof(Struct1) * total];

I suspect this is because I need to do sizeof(_myVar) + sizeof(Struct1) * total instead of just sizeof(_myVar), so because of the pointer addresses that are different I end up with bad data. I think I'm not copying the data correctly into my structure.
Any help would be greatly appreciated!


Solution

  • You need to write the contents of Struct1 separately:

    myData = [NSMutableData dataWithBytes:&_myVar length:sizeof(_myVar)];
    [myData appendBytes: _myVar.arrayOfStructs length: (_myVar.total * sizeof(Struct1)];
    

    When you read it back, you need to read the first part of it, ignore the value of arrayOfStructs that you read, reallocate it based on the length, and read the remainder of it into the newly allocated pointer.