2016-03-21 4 views
4

Мне нужно создать массив структур. Пока я не запустил программу, я буду знать, сколько структур мне нужно будет хранить в массиве. План состоял в том, чтобы передать указатель на структуру функции, которая будет считывать данные в нее, но я делаю сомнительную ошибку. Вот код, чтобы проиллюстрировать то, что я пытаюсь сделать:Размер c массива структуры во время выполнения

#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 

typedef struct { 
    int myVar; 
} myStruct; 

myStruct *myBigList = NULL; 

int defineMyList(myStruct **myArray) { 
    int i = 0, size = rand() % 10; 
    *myArray = malloc(size * sizeof *myArray); 

    for (i = 0; i < size; i++) { 
     myStruct *aStruct = malloc(sizeof(myStruct)); 
     aStruct->myVar = i + 1; 
     myArray[i] = aStruct; 
    } 
    return size; 
} 

int main() { 
    int size = 0, i = 0; 
    srand(time(NULL)); 

    size = defineMyList(&myBigList); 

    for (i = 0; i < size; i++) 
     printf("myBigList[%i].myVar: %i\n", i, myBigList[i].myVar); 

    return EXIT_SUCCESS; 
} 

Я приспособил этот код из another question, что была проблема, похожий на мой.

Моя проблема заключается в том, что, когда я пытаюсь напечатать массив в основном после того как я положил в него данные я просто получаю это:

myBigList[0].myVar: 1 
myBigList[1].myVar: 0 
myBigList[2].myVar: 0 
myBigList[3].myVar: 0 
myBigList[4].myVar: 0 

Когда я ожидал этого:

myBigList[0].myVar: 1 
myBigList[1].myVar: 2 
myBigList[2].myVar: 3 
myBigList[3].myVar: 4 
myBigList[4].myVar: 5 

I Подозреваю, что я неправильно понял что-то с индексацией и указателями. Когда я запускаю программу с valgrind, она сообщает "Invalid read of size 4 at 0x40074D: main" и "Address 0x51fc0d4 is 0 bytes after a block of size 4 alloc'd at 0x4C2AB80: malloc".

+2

@chqrlie Почему вы изменили отступы? Это было прекрасно. – fuz

+0

'sizeof * myArray' - размер указателя, а не структуры – Soren

+0

Кроме того,' myArray [i] 'должен быть' (* myArray) [i] ', и это' struct myStruct' не указатель, и я оставлю это вам, чтобы понять, почему это так. – immibis

ответ

4

Вы путаете себя с косвенностью. Изменить на:

int defineMyList(myStruct **myArray) 
{ 
    int i = 0, size = rand() % 10; 
    *myArray = malloc(size * sizeof **myArray); // Note two ** 

    for(i = 0; i < size; i++) { 
    (*myArray)[i].myVar = i + 1; 
    } 

    return size; 
} 

или даже лучше, избежать запутанные окольные целиком:

int defineMyList(myStruct **myArray) 
{ 
    int i = 0, size = rand() % 10; 

    myStruct * new_array = malloc(size * sizeof *new_array); 
    if (!new_array) { 
     perror("couldn't allocate memory for new array"); 
     exit(EXIT_FAILURE); 
    } 

    for (i = 0; i < size; ++i) { 
     new_array[i].myVar = i + 1; 
    } 

    *myArray = new_array; 
    return size; 
} 
2

Существует немного неправильный код. В вашем коде myBigList является указателем на массив структур. Память для структур уже находится в массиве (она хранит структуры вместо указателей на структуры), поэтому вам не нужно выделять память для каждого элемента структуры.

Ваш код не должен компилироваться при попытке назначить указатель на структуру члену массива (который является структурой, а не указателем на структуру), но он преуспевает из-за другой ошибки. Помните, что myArray является указателем на массив, а не сам массив, так что вместо

myArray[i] = aStruct; 

вы должны иметь письменные

(*myArray)[i] = aStruct; 

и компиляция провалились бы, как это должно быть. Чтобы исправить ваш код, замените весь цикл следующим образом:

for(i = 0; i < size; i++) { 
    (*myArray)[i].myVar = i + 1; 
    } 

и узнать больше о указателях, чтобы понять, почему эта проблема возникла.

Как писал Пол Гриффитс, вам также необходимо изменить звонок malloc(), чтобы использовать правильный размер. Помните, что вы хотите выделить элементы массива size. Размер элемента массива равен (*myArray)[0] или равно **myArray; *myArray - размер указателя на структуру, которой недостаточно.

1

распределение памяти должно выглядеть следующим образом

*myArray = malloc(size * sizeof **myArray); 

Помните идиома

p = malloc(n * sizeof *p); 

Т.е.вы должны иметь один дополнительный * под номером sizeof. Если ваш p составляет *myArray, тогда под номером sizeof вы должны иметь **myArray.

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