2013-03-20 2 views
0

Я провел обширные исследования, прежде чем задавать этот вопрос здесь, но я не мог найти ответа.Как использовать динамический массив C внутри структуры

У меня есть простая структура, которая содержит массив другой структуры и общее:

typedef struct { 
    int total; 
    struct Struct1 arrayOfStructs[]; 
} Struct2; 
Struct2 _myVar; // the variable I need 
  • arrayOfStructs[] должен быть массивом C, содержащие структуры типа Struct1 (этот синтаксис не действует, потому что вам нужен постоянная величина)
  • total является подсчет arrayOfStructs
  • (Struct1 не имеет значения, он просто содержит некоторые примитивные данные)

Проблема в том, что я хочу, чтобы этот массив был динамическим. Я хочу быть в состоянии сделать это:

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

Я попытался следующие:

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

и для добавления значений:

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 

Приведенный выше код добавляет значение правильно, но после того, как передавая его в NSData и извлекая его, элементы массива теряются, и я получаю некоторые плохие указатели:

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

Я подозреваю, что это связано с тем, что мне нужно сделать sizeof(_myVar) + sizeof(Struct1) * total вместо sizeof(_myVar), поэтому из-за разных адресов указателей я получаю плохие данные. Я думаю, что не правильно копирую данные в свою структуру.
Любая помощь будет принята с благодарностью!

+3

Если вы используете указатель 'struct Struct1 * arrayOfStructs;', вы не знаете, где находится полезная нагрузка. Вы можете быть уверены, что это не будет непосредственно после 'Struct2 _myVar;'. Итак, если '[NSData dataWithBytes: & _ myVar length: sizeof (_myVar) + sizeof (Struct1) * total];' принимает 'sizeof _myVar + total * sizeof (Struct1)' байт, начиная с '& _myVar'; который возьмет «int», указатель и много мусора, на которые вы не имеете права. –

+0

Я понимаю, спасибо. И как я мог делать то, что мне нужно, я даже могу изменить способ добавления данных в NSData, но я не уверен, как это сделать. – Calin

ответ

2

Вы должны написать содержание Struct1 отдельно:

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

Когда вы читаете его обратно, вы должны прочитать первую часть, игнорировать значение arrayOfStructs, что вы читаете, перераспределить его на основе длины , и прочесть оставшуюся часть его в недавно выделенный указатель.

1

_myVar - это переменная Struct2. Таким образом, он имеет только целое число и указатель. Массив структур не принадлежит _myVar.

И вот, есть ошибка с длиной для NSData. В & _myVar существует только структура размера sizeof (Struct2).

1

В C обычно используется массив размером 1 в конце структуры. Не знаю, является ли он стандартным в Objective-C. Перераспределение с

(total- 1) * sizeof(Struct1) + sizeof(Struct2) 

может работать.

думаю.

Edit:

Я имею в виду, вы можете сделать что-то вроде:

Это будет ваш-структуру:

typedef struct { 
    int total; 
    struct Struct1 arrayOfStructs[1]; 
} Struct2; 
Struct2 *_myVar = malloc(sizeof(Struct2)); 

И это, как вы добавляете элемент:

int total = ++_myVar->total; 
realloc(_myVar, (total - 1) * sizeof(Struct1) + sizeof(Struct2)); 
_myVar->arrayOfStructs[total - 1] = {1, 5.3}; 

или что-то в этом роде

0

Отслеживать количество элементов в массиве. Чтобы добавить ребенка, повторно вызовитеoc, memcpy и установите дочерний элемент в массиве.

typedef struct Person { 
    char *name; 
    short age; 
    struct Person *children; 
    int numberOfChildren; 
} Person; 


#import <Foundation/Foundation.h> 
int main(int argc, char *argv[]) { 
    @autoreleasepool { 

     NSData *data; 
     { 
      // setup Carol 
      Person ethan = { .name="Ethan", .age=14, .children=nil, .numberOfChildren=0 }; 
      Person terry = { .name="Terry", .age=16, .children=nil, .numberOfChildren=0 }; 
      Person carol = { .name="Carol", .age=40, .children=nil, .numberOfChildren=2 }; 
      carol.children=(Person *)calloc(carol.numberOfChildren, sizeof(&carol)); 
      carol.children[0] = ethan; 
      carol.children[1] = terry; 

      // people 
      Person *people = (Person *)calloc(1+carol.numberOfChildren, sizeof(*people)); 
      people[0] = carol; 

      size_t bytesToCopy = 1+carol.numberOfChildren * sizeof(*people); 
      data = [NSData dataWithBytes:people length:bytesToCopy]; 
     } 

     { 
      int elements = 1 + [data length]/sizeof(Person); 
      Person *people = (Person *)calloc(elements, sizeof(*people)); 
      size_t bytesToCopy = [data length]; 
      const void *source = [data bytes]; 
      memcpy((void*)people, source, bytesToCopy); // memxxx are an ARC no-no 

      for (int i = 0; i < 1; i=i+people[i].numberOfChildren) { 
       printf("\nname=%s, age=%d, children=%d", people[i].name, people[i].age, people[i].numberOfChildren); 
       for (int j = 0; j < people[i].numberOfChildren; j++) { 
        printf("\nname=%s, age=%d, children=%d", people[i].children[j].name, people[i].children[j].age, people[i].children[j].numberOfChildren); 
       } 
      } 
     } 

    } 
} 

Печать

name=Carol, age=40, children=2 
name=Ethan, age=14, children=0 
name=Terry, age=16, children=0 

Рассмотрим избежать всего этого и переход к объектам.

Смежные вопросы