Указатель на структуру, содержащую массив

У меня есть простая структура, содержащая массив целых чисел и индекс, который будет использоваться для этого массива.

#define BUFF_SIZE 100
typedef struct _buffer Buffer;

struct _buffer {
    int buff[BUFF_SIZE];
    int index;
};

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

...
Buffer* newBuff;
newBuff->buff = {0}; //Error occurs here
...

Я знаю, что в c массив является указателем на базу блока памяти, в котором находится массив, но у меня сложилось впечатление, что разыменование указателя структуры позволит мне получить доступ к массиву. Я ошибаюсь в этом, или я что-то упускаю здесь? У меня такое ощущение, что это что-то очень простое, но хоть убей, я просто не могу этого заметить.

Спасибо!

РЕДАКТИРОВАТЬ: Спасибо за быстрые ответы, ребята, они помогли мне понять кое-что из того, что происходит. Я забыл упомянуть, что это предназначено для запуска во встроенной системе (извините за это), поэтому я хотел бы избежать использования include или malloc, если это вообще возможно.


person Legatus42    schedule 15.03.2014    source источник


Ответы (4)


Здесь есть несколько видов путаницы. Указатель указывает на память (ага), но вам нужно откуда-то получить эту память. Как вы инициализируете эту память, это отдельно.

Вы можете разместить свою структуру в стеке, объявив локальную переменную внутри вашей функции:

// Initialize all buff elements and index to 0
// Note: Buffer, not Buffer*
Buffer newBuf = { {0}, 0 };  

Или вы можете выделить его в куче:

Buffer *newBuf = malloc(sizeof(Buffer));
memset(newBuf, 0, sizeof(Buffer));

При размещении объектов в стеке они действительны только во время выполнения текущей функции. Вы не можете вернуть указатель на объект в стеке. Кроме того, пространство стека обычно ограничено, поэтому вы не можете помещать туда объекты размером в мегабайт. При выделении памяти в куче с помощью malloc() вам нужно позаботиться о free(), когда она больше не используется, иначе произойдет утечка памяти.

Вы видите, что при размещении объектов в стеке вы можете использовать список инициализаторов { {0}, 0 }. В случае с кучей вы не можете этого сделать, и вам нужно обнулить память вручную с помощью memset.

person Christian Aichinger    schedule 15.03.2014

Проблема не в стрелочном операторе ->, а в правой части присваивания: {0} в инициализаторах разрешено, но вот так присваивать массив нельзя. Вам нужно использовать memset, чтобы обнулить элементы массива:

memset(newBuff->buff, 0, sizeof(newBuff->buff));

Примечание: ваш код не устанавливает newBuf в допустимое место в памяти. Сначала вам нужно выделить память, например:

newBuff->buff = malloc(sizeof(*newBuff));
person Sergey Kalinichenko    schedule 15.03.2014

Я должен не согласиться с @dasblinkenlight, но я думаю, что проблема в том, что newBuff — это указатель, но ему не присвоено значение. Следовательно, когда вы разыменовываете его, вы, вероятно, получите сбой или непредсказуемые результаты.

У вас должно быть заявление, похожее на:

newBuff = malloc(sizeof (Buffer));

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

Если только я не упускаю что-то ужасно очевидное...

person Eric    schedule 15.03.2014
comment
Сарказм не помогает. Он не указал платформу или версию компилятора. Также могут быть задействованы другие факторы, поскольку он предоставил не всю свою кодовую базу, а только фрагменты. Учитывая эти ограничения, я могу дать только обоснованное предположение об ответе. Я предпочитаю сделать это и дать понять, что я есть, и попытаться быть полезным, чем вести ОП (один из его первых постов) по тропе первоцвета, которая может быть неправильной в его конкретных обстоятельствах. - person Eric; 15.03.2014
comment
Прошу прощения, без сарказма, но если вы посмотрите на два ответа, получивших наибольшее количество голосов, у них обоих есть правильные ответы, которые не требуют дополнительных подробностей. - person Shafik Yaghmour; 15.03.2014

Из вашего вопроса я смог понять - вы хотите инициализировать все элементы массива структурной переменной buff[ ] нулем.

Функция memset() из файла <string.h> поможет вам решить эту проблему.

Как вы сказали, вы пишете код для встроенной системы, поэтому нет необходимости включать весь файл <string.h> в вашу программу.

Я попытался воспроизвести вашу программу и нашел следующее решение:

void *memset(void * , int , size_t ) __attribute__((__nonnull__(1)));

#define BUFF_SIZE 100

typedef struct _buffer Buffer;

struct _buffer {
    int buff[BUFF_SIZE];
    int index;
};

int main (void)
{
    Buffer* newBuff;
    memset(newBuff->buff, 0, BUFF_SIZE);
}

Пожалуйста, дайте мне знать, если это было полезно.

person Nitin Jadhav    schedule 15.03.2014