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) до того, как она будет возвращена, и что структура будет удалена.
Однако, когда я использую свою структуру как это, она, похоже, не удаляется.
Итак, мой вопрос:
Нужно ли мне перестраивать эту структуру и почему?/почему бы и нет?
Ответы
Ответ 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);
Это, скорее всего, даст код, эквивалентный лучшему коду, на который можно было бы надеяться использовать возвращаемую переменную типа структуры, поскольку данные структуры будут помещены прямо в его конечное место без необходимости копирования структуры.