- 1
- 2
- 3
- 4
char (&getArray())[11] {
static char arr[] = "1234567890";
return arr;
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
0
char (&getArray())[11] {
static char arr[] = "1234567890";
return arr;
}
Как вернуть массив из функции в C/C++
На самом деле нет: возвращается ссылка
А кроме того это что-то еще и само указывает на стат литерал, который вообщзе небось никуда не денеца
Функция возвращает ссылку на этот массив.
На многих платформах эта секция ещё и не защищена от записи (в ту же секцию помещаются переменные с начальным значением), так что теоретически можно этот литерал испортить.
Можно не потому что стандарт разрешает (разрешение спрашивать нужно только анскильным питухам вроде тебя), а потому что это работает.
Этот код портит значение массива static char arr[], объявленного внутри функции. Причём в ассемблерном выхлопе никакого копирования нет, портится оригинал:
Если же написать сразу return "1234567890", то константа "1234567890\0" помещается в секцию .rdata, а не .data. Некоторые линкеры и некоторые ОС защищают такую секцию от записи, некоторые — нет. Но в любом случае с точки зрения C++ это уже будет const char, поэтому без const_cast изменить не дадут.
static char arr2[] = "1234567890"; // а тут никакого копирования
Во втором случае начальное значение объявляется сразу на месте, на том самом, где расположена переменная.
капитан
улыбнитесь
На моей платформе оба литерала попали в секцию .rdata, защищённую от записи, поэтому на строке stroka[0] = '9'; программа упала.
Исправляем: gcc -S, меняем секцию с .rdata на .data (представим себе, что у нас линкер использует платформу типа a.out, где нет .rdata), собираем... литерал чудесным образом испортился.
Ты строковый литерал от массива отличаешь? Иди матчасть поучи, питух.
там лямбд нет
> когда можно просто в струхтуру?
std::array так и делает.
Они и не нужны. Их придумали анскильные питухи, не осилившие указатели на функции.
> std::array
Питух, убери от меня это говно. Питух не осилил вернуть массив из функции, и придумал это говно.
С точки зрения исходника кажется, что функция способна возвращать массив или строку по значению. На самом же деле вызывающий код выделяет память под результат (в стеке рядом с локальными переменными), а потом передаёт в функцию указатель на этот блок памяти последним аргументом. С точки зрения ассемблерного выхлопа у функции становится на один аргумент больше. Похожий трюк (с невидимым в исходнике аргументом) происходит при вызове методов объектов, но там указатель на self передаётся первым аргументом.
Эквивалентный код: Тут явная передача по ссылке, но тут нужно явно же заводить переменную под результат, а в случае функции результат был безымянным. Вызов функции getArray компилируется в такое:
Опять это экспортное законодательство...
Если завернуть в структуру, то сишка/кресты поступают так же, как Паскаль:
Ассемблерный выхлоп:
Если же я сделаю typedef char pituh_type[11], то компилятор ругнётся: Он согласится компилировать код, только если объявить pituh_type & getArray(), и в этом случае в eax/rax вернёт ссылку.
Почему в сишке и в крестах так недолюбливают массивы, что их обязательно нужно завернуть в структуру, чтобы передать по значению?
оно вообще сконпелицца?
https://ideone.com/SNuZfm
Короче, иди в свой «Сосач» или в свои «Одноклассники». Там твоя аудитория.
Кстати, для сомневающихся: в Турбо Паскале и в его потомках массивы of char можно инициализировать строковым литералом. Если литерал короче массива, хвост добивается байтами, равными нулю. Наоборот же (если массив короче литерала) не работает.
Самая ватная версия, кстати: у TP6 даже была кустарная русификация IDE (мне, правда, такой мутант не попадался).
P.S. Ещё Тарас знает.
http://pascalabc.net/downloads/pabcnethelp/index.htm?page=Common/PABCNETvsDelphi.html
И инициализации массивов строковым литералом в нём тоже нет.
Плохо сделали, тупо.
Ещё и сайт на фреймах, так что я сначала неправильную ссылку скопировал. Какой анскилл )))
Странно, что они добавили много интересного, но при этом много интересного убрали вроде записей с вариантами и вариантных типов. И вот даже такую мелочь убрали, как инициализация массивов строковым литералом. Нужно явно писать ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') вместо '1234567890'.
В общем, сасай.
Ватники даже в пассаль не могут, дно пробито!
а если static убрать?
2. скомпилируется с ворнингом "returning a reference to local", возможно будет рабтать, но это неточно.
2. пушо строковой литерал?
а если сделать 1 и 2?
2. Нет, потому что UB
3. Будет 1 и 2
и что? ну я создал массив челочисленных типов на стеке, и вернул на него ссылку.
Массив закончился в месте с функцией, разве нет?
>2. Нет, потому что UB
почему нельзя вернуть ссылку на статическую переменную?
Согласно стандарту. Что компилятор сделает -- вопрос отдельный.
> почему нельзя вернуть ссылку на статическую переменную?
потому, что можно, АПВС?
1. Вернуть массив по стандарту нельзя. Это UB.
2. Но если он статический то можно. По стандарту.
3. Если массив инициализрован строковым литералом, но возвращать его все равно UB. Но почти всегда это будет работать. Потому что литералы никуда не деваются. Но могут. Но не деваются.
Верно?
Нет, просто нельзя. Не скомпилируется: нет соответствующего синтаксиса. А в примере возвращается ссылка (читай текст под спойлером).
> 2. Но если он статический то можно. По стандарту.
В контексте №1, все так же нельзя. Но ссылку вернуть можно, и это не UB.
> 3. Если массив инициализрован строковым литералом, но возвращать его все равно UB. Но почти всегда это будет работать. Потому что литералы никуда не деваются. Но могут. Но не деваются.
Да.
>Да.
Шта?
Какая разница, чем массив инициализирован, данные все равно скопируются в стек. UB.
Подождите-ка. Я всегда думал, что время жизни строкового литерала должна быть вся программа. Неужели по стандарту это не так?
char *s = "petutuh"; это указатель на статическую область памяти, а char s[] = "petuhuh"; это заполнение выделенного в стеке массива.
Проверил, как ведёт себя gcc.
1. В C++ вернуть массив нельзя. Можно вернуть только ссылку на массив, явно указав & у типа результата функции.
2. В Си вернуть массив тоже нельзя, но в Си нет ссылок. Можно вернуть указатель на массив (что по сути будет указателем на указатель) либо указатель на начальный элемент массива либо завернуть массив в структуру.
guest> 3. можно вернуть указатель на первый элемент массива
В общем, мы имели в виду одно и то же. char * вернуть можно, а char [] почему-то нельзя, хотя в сишке они обычно синонимы (char petuh[42] можно засунуть в return, хотя return должен вернуть значение типа char *).
Ну видимо аукционом продаваться будет, поэтому только стартовая цена. Если никому нахуй не нужен - за 600 и купишь.