Возврат указателя структуры

Предположим, что у меня есть следующая структура и функция, возвращая указатель:

typedef struct {
  int num;
  void *nums;
  int size;
} Mystruct;

Mystruct *mystruct(int num, int size)
{ 
   //Is the following correct? Is there a more efficient way?
   Mystruct mystruct;
   mystruct.num = num;
   mystruct.size = size;
   mystruct.nums = malloc(num*sizeof(size));
   Mystruct *my;
   *my = mystruct;
   return my;
}

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

22
задан N 1.1 24 April 2010 в 02:25
поделиться

6 ответов

Если я объявлю переменную Mystruct, определите свойства Mystruct, {{1 }} присвоить ему указатель и вернуть указатель

Определенно нет, потому что переменная, определенная в функции (в классе хранения "auto"), исчезнет при выходе из функции, и вы вернете свисающий указатель.

Вы можете принять указатель на Mystruct (ответственность вызывающего за его выделение) и заполнить его; или вы можете использовать malloc , чтобы создать новый (ответственность вызывающего абонента освободить его, когда это будет сделано). Второй вариант, по крайней мере, позволяет сохранить сигнатуру функции, которая кажется вам интересной:

Mystruct *mystruct(int num, int size)
{
   Mystruct *p = malloc(sizeof(MyStruct));
   ....
   return p;
}

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

36
ответ дан 29 November 2019 в 04:08
поделиться

Еще один способ сделать это ..

int mystruct(Mystruct *mystruct, int num, int size){
   if(mystruct == NULL)
      return -1;

   mystruct->num = num;
   mystruct->size = size;
   ::
   return 0;
}

int main(){
   Mystruct my;

   if(mystruct(&my, 3, 4) != 0){
      fprintf(stderr, "Cannot init!\n");
      exit(0);
   }
   ::
}
2
ответ дан 29 November 2019 в 04:08
поделиться

Если вы пишете общий код, а не знать, как его можно использовать, хорошо предоставить оба варианта:

int mystructm(Mystruct *storage, int num, int size)
{
    int rv = 0;

    storage->num = num;
    storage->size = size;
    storage->nums = malloc(num*sizeof(size));
    if (!storage->nums)
        return -1;

    return 0;
}

Mystruct *mystruct(int num, int size)
{
    Mystruct *mp = (Mystruct *)malloc(sizeof(Mystruct));
    if (mp)
    {
        if (mystructm(mp, num, size) == -1)
        {
            free(mp);
            mp = NULL;
        }
    }

    return mp;
}

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

3
ответ дан 29 November 2019 в 04:08
поделиться

Важно помнить, что указатель - это не то, что вы назначаете структуре, а, скорее, указатель указывает место в памяти, которое вы хотите рассматривать как состав. Основываясь на вашем вопросе, вы действительно хотите выделить память для хранения структуры данных. Это дает вам указатель на выделенную ячейку памяти. Как только вы его получите, вы можете вернуть его.


РЕДАКТИРОВАТЬ (после редактирования исходного вопроса) При просмотре вашего редактирования вопроса у вас определенно возникнут проблемы с указателем «мой». Он не инициализирован и может указывать на любое место в памяти. Когда вы попытаетесь скопировать в него структуру, вы, вероятно, получите ошибку сегментации.

2
ответ дан 29 November 2019 в 04:08
поделиться

Назначение новой Mystruct и возврат указателя на нее обычно будет выглядеть примерно так:

Mystruct *mystruct(int num, int size)
{
   Mystruct *result;

   result = malloc(sizeof(MyStruct));
   if (!result)
     return NULL;

   result->num = num;
   ...

   return result;
}

Позже, когда вы выполняются с помощью Mystruct , размещенного здесь с помощью malloc , его нужно снова освободить с помощью free () .

Простое объявление локальной переменной и возврат указателя на эту локальную переменную не сработают. Локальная переменная выходит за пределы области видимости в конце функции, и память, в которой она хранилась, скорее всего, повторно используется для других целей. Возвращенный указатель по-прежнему будет указывать на место в памяти, где когда-то была локальная переменная, но поскольку эта переменная больше не существует, этот указатель не будет иметь большого смысла.

2
ответ дан 29 November 2019 в 04:08
поделиться

Вы не можете использовать переменную, потому что она будет освобождена при выходе из функции. Например:

Mystruct *mystruct(int num, int size)
{
   MyStruct x;
   x.num = 1;
   ...
   return &x;
}

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

Mystruct *mystruct(int num, int size)
{
   MyStruct *x;
   x = (MyStruct*)malloc( sizeof( MyStruct ) );
   x->num = 1;
   ...
   return x;
}
7
ответ дан 29 November 2019 в 04:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: