Подтвердить что ты не робот

ANSI C вам нужно использовать malloc() при создании структуры?

Скажем, у меня есть эта структура в ANSI C:

typedef struct _point
{
    float x;
    float y;
} Point;

и эту функцию для создания этой структуры:

Point createpoint(float x, float y)
{
    Point p;
    p.x = x;
    p.y = y;
    return p; 
}

Это позволяет мне создать структуру с этой функцией i.e:

int main()
{
    Point pointOne = createpoint(5, 6);  
    Point pointTwo = createpoint(10, 4);
    float distance = calculatedistancefunc(pointOne, pointTwo);

    /* ...other stuff */

    return 0;
}

теперь мой вопрос; кто-то сказал мне, что этот код недействителен, потому что структура не получает malloc'd в функции createpoint (float x, float y) до того, как она будет возвращена, и что структура будет удалена. Однако, когда я использую свою структуру как это, она, похоже, не удаляется.

Итак, мой вопрос: Нужно ли мне перестраивать эту структуру и почему?/почему бы и нет?

4b9b3361

Ответ 1

Что бы вы ни делали, это совершенно правильно. Заявление -

return p;

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

Point createpoint(float x, float y)
{
    Point p;
    p.x = x;
    p.y = y;
    return p; 
} // p is no longer valid from this point. So, what you are returning is a copy of it.

Но -

Point* createpoint(float x, float y)
{
    Point *p = malloc(sizeof(Point));
    p->x = x;
    p->y = y;
    return p; 
}// Now you returning the object what p is pointing to.

Ответ 2

Вы можете вернуть struct в стек, ваш код действителен. Проблема возникла бы, если бы вы вернули указатель на локальную переменную, но это не то, что вы делаете, вы возвращаете копию, это прекрасно.

Ответ 3

C99 допускает даже более приятное создание структур на основе стека.
Учитывая приведенную ниже структуру

typedef struct
{
    float x;
    float y;
} Point;

вы можете инициализировать его в немного стиля конструктора С++ со следующим утверждением:

Point p = (Point){0.4, 0.5};

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

int main()
{
    Point pointOne = (Point){5, 6};
    Point pointTwo = (Point){10, 4};
    float distance = calculatedistancefunc(pointOne, pointTwo);
    //...other stuff
    return 0;
}

Ответ 4

Point createpoint(float x, float y)
{
    Point p;
    p.x = x;
    p.y = y;
    return p; 
} /

Все локальные переменные в функции удаляются. after возвращает функции.

1 > передать по ссылке Поэтому, если вы возвращаете указатель на эту локальную переменную, то после возврата функции эти переменные удаляются, поэтому указатели недействительны.

2 > передать значение Но здесь вы возвращаете копию этой локальной переменной, поэтому ее безопасно, потому что локальная переменная gona dead при возврате функции, но копия возвращаемого значения будет сохранена в переменной приемника при вызове функции перед возвратом функции.

Ответ 5

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

StructType BuildStruct(void)
{
  StructType it;
  it.this=4;
  it.that=23;
  return it;
}

StructType myStruct;
myStruct = BuildStruct();

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

Альтернативный дизайн:

void BuildStruct(StructType *it)
{
  it->this=4;
  it->that=23;
}

StructType myStruct;
BuildStruct(&myStruct);

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