Я знаю, что в C мы не можем вернуть массив из функции, а только указатель на массив. Но я хочу знать, в чем особенность, structs
которая делает их возвращаемыми функциями, даже если они могут содержать массивы.
Почему struct
упаковка делает действующей следующую программу?
#include <stdio.h>
struct data {
char buf[256];
};
struct data Foo(const char *buf);
int main(void)
{
struct data obj;
obj = Foo("This is a sentence.");
printf("%s\n", obj.buf);
return 0;
}
struct data Foo(const char *buf)
{
struct data X;
strcpy(X.buf, buf);
return X;
}
union
. Что особенного в союзах?memcpy()
и потеря «скрытая» памяти является основной причиной того, что структура не должна бытьpassed to
ниreturned from
функцией. Лучшая политика - передать указатель на структуру.Ответы:
Лучше задать тот же вопрос: «Что особенного в массивах?», Поскольку особая обработка связана с массивами, а не с массивами
struct
.Поведение передачи и возврата массивов с помощью указателя восходит к исходной реализации C. Массивы «распадаются» на указатели, вызывая большую путаницу, особенно среди людей, плохо знакомых с языком. Структуры, с другой стороны, ведут себя так же, как встроенные типы, такие как
int
s,double
s и т. Д. Сюда входят любые массивы, встроенные вstruct
, за исключением гибких элементов массива , которые не копируются.источник
struct
s по значению была невозможной?struct Point {short x, y, z;};
. Вы действительно хотите использовать указатели для их перемещения? Вы точно не экономите место таким образом.Прежде всего, процитируем
C11
главу §6.8.6.4,return
утверждение ( выделено мной )Возврат структурной переменной возможен (и верен), поскольку возвращается структурное значение . Это похоже на возврат любого примитивного типа данных (например, возврат
int
).С другой стороны, если вы возвращаете массив с помощью
return <array_name>
, он по существу возвращает адрес первого элемента массива ПРИМЕЧАНИЕ. , который становится недействительным для вызывающей стороны, если массив был локальным для вызываемых функций. Таким образом, возврат массива таким способом невозможен.Так, TL; DR , нет ничего особенного с
struct
с, специальность в массивах .ЗАМЕТКА:
C11
Снова цитируя главу §6.3.2.1 ( выделено мной )источник
В
struct
типах нет ничего особенного ; дело в том, что в типах массивов есть что-то особенное, что не позволяет им напрямую возвращаться из функции.struct
Выражение рассматривается как выражение любого другого типа без массива; он оценивает на значение изstruct
. Итак, вы можете делать такие вещи, какstruct foo { ... }; struct foo func( void ) { struct foo someFoo; ... return someFoo; }
Выражение
someFoo
вычисляется в значение этогоstruct foo
объекта; содержимое объекта возвращается из функции (даже если это содержимое содержит массивы).Выражение массива трактуется иначе; если это не операнд
sizeof
унарных&
операторов или, или если это не строковый литерал, используемый для инициализации другого массива в объявлении, выражение преобразуется («распадается») из типа «массивT
» в «указатель наT
» , а значение выражения - это адрес первого элемента.Таким образом, вы не можете вернуть массив по значению из функции, потому что любая ссылка на выражение массива автоматически преобразуется в значение указателя.
источник
По умолчанию структуры имеют открытые члены данных, поэтому в случае структуры можно получить доступ к данным в основном, но не в случае класса. Итак, обертка структуры действительна.
источник
public
/private
различий и нетclass
es. Вопрос в том, зачемstruct
нужен C для возврата значения массива.