- 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++
На самом деле нет: возвращается ссылка
Elvenfighter 24.10.2019 18:02 # 0
MAPTbIwKA 24.10.2019 18:09 # 0
zip 24.10.2019 18:41 # 0
MAKAKA 24.10.2019 18:56 # 0
А кроме того это что-то еще и само указывает на стат литерал, который вообщзе небось никуда не денеца
zip 24.10.2019 20:30 # 0
Функция возвращает ссылку на этот массив.
На многих платформах эта секция ещё и не защищена от записи (в ту же секцию помещаются переменные с начальным значением), так что теоретически можно этот литерал испортить.
guest8 24.10.2019 23:10 # −999
superhackkiller197 24.10.2019 23:21 # 0
Можно не потому что стандарт разрешает (разрешение спрашивать нужно только анскильным питухам вроде тебя), а потому что это работает.
guest8 24.10.2019 23:30 # −999
guest8 25.10.2019 00:51 # −999
eszett 06.11.2019 16:58 # 0
koshka_Sviborga 06.11.2019 19:39 # 0
Этот код портит значение массива static char arr[], объявленного внутри функции. Причём в ассемблерном выхлопе никакого копирования нет, портится оригинал:
Если же написать сразу return "1234567890", то константа "1234567890\0" помещается в секцию .rdata, а не .data. Некоторые линкеры и некоторые ОС защищают такую секцию от записи, некоторые — нет. Но в любом случае с точки зрения C++ это уже будет const char, поэтому без const_cast изменить не дадут.
guest8 06.11.2019 19:45 # −999
koshka_Sviborga 06.11.2019 19:47 # 0
static char arr2[] = "1234567890"; // а тут никакого копирования
Во втором случае начальное значение объявляется сразу на месте, на том самом, где расположена переменная.
guest8 06.11.2019 19:50 # −999
Rooster 06.11.2019 23:47 # 0
MAPTbIwKA 07.11.2019 01:00 # 0
капитан
улыбнитесь
koshka_Sviborga 06.11.2019 19:45 # 0
На моей платформе оба литерала попали в секцию .rdata, защищённую от записи, поэтому на строке stroka[0] = '9'; программа упала.
Исправляем: gcc -S, меняем секцию с .rdata на .data (представим себе, что у нас линкер использует платформу типа a.out, где нет .rdata), собираем... литерал чудесным образом испортился.
MAKAKA 24.10.2019 18:54 # 0
Elvenfighter 24.10.2019 19:24 # 0
MAKAKA 24.10.2019 19:43 # 0
Elvenfighter 24.10.2019 20:27 # 0
superhackkiller197 24.10.2019 23:19 # 0
Ты строковый литерал от массива отличаешь? Иди матчасть поучи, питух.
MAPTbIwKA 07.11.2019 01:01 # 0
superhackkiller197 07.11.2019 01:09 # 0
Elvenfighter 24.10.2019 19:25 # 0
там лямбд нет
> когда можно просто в струхтуру?
std::array так и делает.
superhackkiller197 24.10.2019 23:24 # 0
Они и не нужны. Их придумали анскильные питухи, не осилившие указатели на функции.
> std::array
Питух, убери от меня это говно. Питух не осилил вернуть массив из функции, и придумал это говно.
guest8 24.10.2019 23:30 # −999
zip 24.10.2019 18:26 # 0
С точки зрения исходника кажется, что функция способна возвращать массив или строку по значению. На самом же деле вызывающий код выделяет память под результат (в стеке рядом с локальными переменными), а потом передаёт в функцию указатель на этот блок памяти последним аргументом. С точки зрения ассемблерного выхлопа у функции становится на один аргумент больше. Похожий трюк (с невидимым в исходнике аргументом) происходит при вызове методов объектов, но там указатель на self передаётся первым аргументом.
Эквивалентный код: Тут явная передача по ссылке, но тут нужно явно же заводить переменную под результат, а в случае функции результат был безымянным. Вызов функции getArray компилируется в такое:
guest8 24.10.2019 18:28 # −999
guest8 24.10.2019 18:29 # −999
guest8 24.10.2019 18:30 # −999
zip 24.10.2019 18:38 # 0
Опять это экспортное законодательство...
guest8 24.10.2019 19:18 # −999
6arop_pycHu 24.10.2019 19:20 # 0
zip 24.10.2019 18:32 # 0
guest8 24.10.2019 18:50 # −999
guest8 24.10.2019 19:17 # −999
guest8 25.10.2019 01:00 # −999
guest8 24.10.2019 19:32 # −999
zip 24.10.2019 20:23 # 0
Если завернуть в структуру, то сишка/кресты поступают так же, как Паскаль:
Ассемблерный выхлоп:
Если же я сделаю typedef char pituh_type[11], то компилятор ругнётся: Он согласится компилировать код, только если объявить pituh_type & getArray(), и в этом случае в eax/rax вернёт ссылку.
Почему в сишке и в крестах так недолюбливают массивы, что их обязательно нужно завернуть в структуру, чтобы передать по значению?
guest8 24.10.2019 21:06 # −999
RMS 25.10.2019 17:18 # 0
6arop_pycHu 24.10.2019 19:14 # 0
оно вообще сконпелицца?
zip 24.10.2019 20:05 # 0
https://ideone.com/SNuZfm
Короче, иди в свой «Сосач» или в свои «Одноклассники». Там твоя аудитория.
guest8 24.10.2019 20:07 # −999
guest8 24.10.2019 20:11 # −999
zip 24.10.2019 20:42 # 0
Кстати, для сомневающихся: в Турбо Паскале и в его потомках массивы of char можно инициализировать строковым литералом. Если литерал короче массива, хвост добивается байтами, равными нулю. Наоборот же (если массив короче литерала) не работает.
6arop_pycHu 24.10.2019 21:12 # 0
guest8 25.10.2019 00:57 # −999
zip 25.10.2019 01:05 # 0
guest8 25.10.2019 01:11 # −999
guest8 25.10.2019 01:29 # −999
zip 25.10.2019 01:52 # +1
Самая ватная версия, кстати: у TP6 даже была кустарная русификация IDE (мне, правда, такой мутант не попадался).
P.S. Ещё Тарас знает.
guest8 25.10.2019 02:20 # −999
nymuHckuu_nemyx 25.10.2019 10:34 # −102
guest8 25.10.2019 01:28 # −999
lha 25.10.2019 05:36 # 0
http://pascalabc.net/downloads/pabcnethelp/index.htm?page=Common/PABCNETvsDelphi.html
И инициализации массивов строковым литералом в нём тоже нет.
Плохо сделали, тупо.
Ещё и сайт на фреймах, так что я сначала неправильную ссылку скопировал. Какой анскилл )))
guest8 25.10.2019 10:16 # −999
lha 25.10.2019 15:41 # 0
Странно, что они добавили много интересного, но при этом много интересного убрали вроде записей с вариантами и вариантных типов. И вот даже такую мелочь убрали, как инициализация массивов строковым литералом. Нужно явно писать ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') вместо '1234567890'.
zip 25.10.2019 01:08 # 0
6arop_pycHu 24.10.2019 21:05 # 0
В общем, сасай.
Ватники даже в пассаль не могут, дно пробито!
MAKAKA 24.10.2019 18:55 # 0
а если static убрать?
Elvenfighter 24.10.2019 19:21 # 0
2. скомпилируется с ворнингом "returning a reference to local", возможно будет рабтать, но это неточно.
MAKAKA 24.10.2019 19:24 # 0
2. пушо строковой литерал?
а если сделать 1 и 2?
Elvenfighter 24.10.2019 19:28 # 0
2. Нет, потому что UB
3. Будет 1 и 2
MAKAKA 24.10.2019 19:32 # 0
и что? ну я создал массив челочисленных типов на стеке, и вернул на него ссылку.
Массив закончился в месте с функцией, разве нет?
>2. Нет, потому что UB
почему нельзя вернуть ссылку на статическую переменную?
Elvenfighter 24.10.2019 19:35 # 0
Согласно стандарту. Что компилятор сделает -- вопрос отдельный.
> почему нельзя вернуть ссылку на статическую переменную?
потому, что можно, АПВС?
MAKAKA 24.10.2019 19:39 # 0
1. Вернуть массив по стандарту нельзя. Это UB.
2. Но если он статический то можно. По стандарту.
3. Если массив инициализрован строковым литералом, но возвращать его все равно UB. Но почти всегда это будет работать. Потому что литералы никуда не деваются. Но могут. Но не деваются.
Верно?
Elvenfighter 24.10.2019 20:09 # +1
Нет, просто нельзя. Не скомпилируется: нет соответствующего синтаксиса. А в примере возвращается ссылка (читай текст под спойлером).
> 2. Но если он статический то можно. По стандарту.
В контексте №1, все так же нельзя. Но ссылку вернуть можно, и это не UB.
> 3. Если массив инициализрован строковым литералом, но возвращать его все равно UB. Но почти всегда это будет работать. Потому что литералы никуда не деваются. Но могут. Но не деваются.
Да.
Steve_Brown 25.10.2019 11:02 # 0
>Да.
Шта?
Какая разница, чем массив инициализирован, данные все равно скопируются в стек. UB.
guest8 25.10.2019 14:15 # −999
Steve_Brown 25.10.2019 14:52 # 0
guest8 25.10.2019 15:22 # −999
Steve_Brown 28.10.2019 11:09 # 0
Подождите-ка. Я всегда думал, что время жизни строкового литерала должна быть вся программа. Неужели по стандарту это не так?
char *s = "petutuh"; это указатель на статическую область памяти, а char s[] = "petuhuh"; это заполнение выделенного в стеке массива.
zip 24.10.2019 20:51 # 0
Проверил, как ведёт себя gcc.
1. В C++ вернуть массив нельзя. Можно вернуть только ссылку на массив, явно указав & у типа результата функции.
2. В Си вернуть массив тоже нельзя, но в Си нет ссылок. Можно вернуть указатель на массив (что по сути будет указателем на указатель) либо указатель на начальный элемент массива либо завернуть массив в структуру.
guest8 24.10.2019 20:54 # −999
guest8 24.10.2019 20:57 # −999
guest8 24.10.2019 21:06 # −999
guest8 25.10.2019 00:52 # −999
guest8 25.10.2019 17:29 # −999
guest8 25.10.2019 21:22 # −999
zip 24.10.2019 21:31 # 0
guest> 3. можно вернуть указатель на первый элемент массива
В общем, мы имели в виду одно и то же. char * вернуть можно, а char [] почему-то нельзя, хотя в сишке они обычно синонимы (char petuh[42] можно засунуть в return, хотя return должен вернуть значение типа char *).
guest8 24.10.2019 21:38 # −999
guest8 24.10.2019 21:47 # −999
guest8 24.10.2019 19:33 # −999
Elvenfighter 24.10.2019 19:38 # 0
guest8 24.10.2019 19:40 # −999
guest8 26.10.2019 00:24 # −999
guest8 26.10.2019 00:46 # −999
guest8 26.10.2019 00:50 # −999
guest8 26.10.2019 00:54 # −999
guest8 06.05.2020 16:37 # −999
bormand 06.05.2020 18:34 # 0
Ну видимо аукционом продаваться будет, поэтому только стартовая цена. Если никому нахуй не нужен - за 600 и купишь.
OCETuHCKuu_nemyx 06.05.2020 19:51 # 0
bormand 10.11.2019 11:06 # 0
koshka_Sviborga 11.11.2019 16:34 # 0
bormand 11.11.2019 18:52 # 0