These are chat archives for dev-ua/rust

18th
Jun 2015
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:01

коллеги, а все таки, кто мне может толково обьяснить в чем же заключается ошибка этого кода?

fn select<T>(v: &Vec<T>) -> Vec<T>{
    unreachable!()
}
fn main() {
    let tail = vec![1,2,3];
    let right = select(&tail.clone()).iter();
}

и почему вот так все же будет работать?
let right = select(&tail.clone()).iter().map(|| 1);
ведь тут же тоже возвращается структура с итератором

Michael Pankov
@mkpankov
Jun 18 2015 13:13
@lividgreen у меня второй вариант не компилируется с адовой какой-то ошибкой
а в первом случае ссылка, которую вы клонируете, живёт только в области видимости аргументов select, т.е. как бы внутри круглых скобок, а должна жить весь блок начиная с объявления right
её можно присвоить куда-то чтобы эта проблема ушла
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:21
блин, что за дела... вчера работало
Michael Pankov
@mkpankov
Jun 18 2015 13:24
@lividgreen вряд ли, разве что вы компилятор обновили :)
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:43
да, не работает... let right = select(&tail.clone()).iter().map(|&x| 1) вот так в смысле правильно. но все равно не работает
вот странно почему вот так работает:
fn select<T>(v: &Vec<T>) -> Vec<T>{
    unreachable!()
}
fn main() {
    let tail = vec![1,2,3];
    let tmp = select(&tail.clone());
    let right = tmp.iter();
}
Michael Pankov
@mkpankov
Jun 18 2015 13:45
@lividgreen ничего странного, так и задумано (по крайней мере, пока)
Rust же время жизни синтаксически оценивает
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:46
но как это понять? почему в первом случае скоуп не может вылезти за скобочки, а во втором это как-бы не важно?
Michael Pankov
@mkpankov
Jun 18 2015 13:47
@lividgreen я вас обманул, там не в этой ссылке дело, вроде
есть какие-то предложения улучшить borrow checker чтобы он сам расширял время жизни в подобных ситуациях, а не требовал введения дополнительного имени
дело в том, что результат select никто не хранит, в исходном варианте
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:47
а ссылочка есть?
Michael Pankov
@mkpankov
Jun 18 2015 13:47
@lividgreen попробую найти
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:48
ну как не хранит, а структура итератора?
Michael Pankov
@mkpankov
Jun 18 2015 13:48
select тут как бы возвращает никуда не привязанный объект, итератор тут не при чём
примерно как let _ = select(&tail.clone());
он "схлопнется" сразу, и не будет жить до конца блока
это как temporary objects в C++
@lividgreen я так понял тут даже что-то уже реализовали, но это не документировано, и, по ходу, не в 1.0 rust-lang/rust#12032
Michael Pankov
@mkpankov
Jun 18 2015 13:54
@lividgreen вот был RFC rust-lang/rust#3511
Nick Palamarchuk
@lividgreen
Jun 18 2015 13:54
а почему его в 1.0 не приняли непонятно
Michael Pankov
@mkpankov
Jun 18 2015 13:58
@lividgreen не успевали вроде
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:06
непонятно, почему тогда работают цепочки других методов
например, v.iter().map(|&i| i + 1).collect()
ведь опять же, iter() возвращает временный объект, который живёт до конца стейтмента, почему же тут не ругается?
Michael Pankov
@mkpankov
Jun 18 2015 14:17
@madkinder потому что v живёт весь блок, включающий этот оператор
это то же самое, что let v = select(&tail.clone()); в нашем примере
Ghost
@ghost~54cac78adb8155e6700f3e5a
Jun 18 2015 14:18
This message was deleted
Nick Palamarchuk
@lividgreen
Jun 18 2015 14:21
получается, что мы не можем вот так просто использовать результат работы голой функции в том же стейтменте, нужно обязательно чтоб она была "подперта" переменной
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:22
т.е. была методом, так?
Nick Palamarchuk
@lividgreen
Jun 18 2015 14:23
не
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:23
грубо говоря select(v).foo() не работает (без временной переменной), а вот v.select().foo()запросто
Nick Palamarchuk
@lividgreen
Jun 18 2015 14:23
let tmp = tail.clone().iter();
вот так будет ошибка
та же самая
Michael Pankov
@mkpankov
Jun 18 2015 14:23
@lividgreen да, имя - это владелец объекта. нет владельца - объект не жилец)
крепостное право в действии :D
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:24
что-то я так и не понял разницы, если честно
почему v.iter().map() работает, а let tmp = tail.clone().iter(); - нет
синтаксически ж один в один
Nick Palamarchuk
@lividgreen
Jun 18 2015 14:25
ну клон как-бы возвращает новый обьект, который не привязан ни к какой переменной... и получается, что iter() не знает на какую переменную сослаться, как-то так)
Michael Pankov
@mkpankov
Jun 18 2015 14:25
да
не как бы, а новый :)
Nick Palamarchuk
@lividgreen
Jun 18 2015 14:25
в случае же v.iter().map() получается, что конечній мап сошлется на переменную v
rust прекрасный язык)
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:27
окей, зайду с другой стороны: чем отличаются определения clone() от iter(), что в одном случае работает, ссылается на v и прочая, а во втором - нет
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 14:27
это у них особый “объектный” режим, про него в тутуориале рассказывается практически сразу
Michael Pankov
@mkpankov
Jun 18 2015 14:27
чего
какой режим
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:28
сколько не читал туториалов, ни про какие режимы не видел
Michael Pankov
@mkpankov
Jun 18 2015 14:28
fn clone(x: T) -> T
fn iter(&self) -> Iter<T>
стало понятнее?
clone создаёт новый объект, которым кто-то должен владеть
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:29
ничуть не стало :(
ни там ни там нет явных lifetime-ов
Michael Pankov
@mkpankov
Jun 18 2015 14:29
iter берёт ссылку на себя, и создаёт объект итератора, внутри которого эта ссылка
время жизни для объекта не нужно, оно применимо только к ссылкам
явно оно указано или нет - не важно
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:30
а что мешает iter-у брать ссылку на себя, но создавать что-либо, что не содержит эту ссылку?
Michael Pankov
@mkpankov
Jun 18 2015 14:30
если оно не указано, это то же самое, что &'a T
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:30
из самого описания ни то ни другое не очевидно
Michael Pankov
@mkpankov
Jun 18 2015 14:30
@madkinder логика его работы :)
итератор держит ссылку на коллекцию же
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:30
да пусть держит себе на здоровье
Michael Pankov
@mkpankov
Jun 18 2015 14:30
по соображениям того, что она нужна ему, чтобы работать :)
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:31
я хочу понять, как компилятор это выясняет
из типов это не очевидно
Michael Pankov
@mkpankov
Jun 18 2015 14:31
что выясняет?
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:31
ссылается ли Iter<T> возвращаемый из iter() на self, передаваемый в качестве параметров
Michael Pankov
@mkpankov
Jun 18 2015 14:32
интересный вопрос
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:34
попутно вопрос, как пользоваться API документацией? :D Вот есть std::Vec, по коду видно, что у него есть метод iter(), но в API docs я ссылку на него в упор найти не могу
Michael Pankov
@mkpankov
Jun 18 2015 14:34
так-то он конечно может смотреть на времена жизни ссылок, Iter определен вроде такого
struct Iter<'a> {
    collection: &'a T
    ...
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:35
соответственно заглянуть в реализацию, и понять, откуда ноги растут становится затруднительно
Michael Pankov
@mkpankov
Jun 18 2015 14:35
вот только я тоже думал, что одного лишь типа должно функции должно быть достаточно для вывода времён жизни
почему, с реализацией всё как раз понятно
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 14:35
https://doc.rust-lang.org/std/vec/struct.Vec.html - есть iter в списке
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:36
ну, судя по определению Iter-а, так и получается, что достаточно. lifetime определён в самом типе возвращаемого значения, просто это явно не видно
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:36
хм... что-то обычный ctrl-f не хотел находить, my bad. А как его исходник глянуть теперь?
Michael Pankov
@mkpankov
Jun 18 2015 14:37
дальше ещё интереснее:
pub struct Iter<'a, T> where T: 'a {
    // some fields omitted
}
@madkinder нажать на Iter, потом справа вверху src
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 14:38
http://snpy.link/IjaHao справа ссылка src
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:38
не-не, я про реализацию именно метода iter(), а не структуры Iter
Michael Pankov
@mkpankov
Jun 18 2015 14:38
тогда на странице Vec вверх прокрутить, там тоже src
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:38
т.е. мне нужна реализация метода Vec#iter
дык в том то и дело, что тыркал на src, дальше поиском - метода iter не нашёл
все 10 вхождений не о том, кажется
Michael Pankov
@mkpankov
Jun 18 2015 14:41
а iter владение не поглощает вроде
ща проверим
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:42
iter_into() поглощает
а просто iter() нет
Michael Pankov
@mkpankov
Jun 18 2015 14:43
херня какая-то, согласен
возможно опубликованный исходник не актуален
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 14:46
ну там и правда мутно, iter если верить докам приходит от Deref трейта, но в исходнике трейта столько методов, сколько в списке, нет. и iter там тоже нет
Michael Pankov
@mkpankov
Jun 18 2015 14:46
есть подозрение, что это потому что Vec неявно приводится к срезу &[T]
пойду в IRC спрошу :D
кстати да, на самом деле
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:51
что-то всё чудесатее и чудесатее :)
если честно, я так и не понял, почему некоторые методы можно чейнить, а некоторые нет
Michael Pankov
@mkpankov
Jun 18 2015 14:53
iter(&self) уже может &self к срезу привести
&Vec<T> приводится к &[T]
это позволяет вызвать iter() у среза &[T]
&Vec<T> приводится к &[T] через типаж Deref у Vec
@madkinder попробуй писать код ;)
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:56
дык пробовал :)
если бы не пробовал вопросов бы не возникало
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 14:57
имхо самый лучший совет в данном случае - “не чейни, не на jQuery пишешь” - но согласен, очень ночевидно все
Michael Pankov
@mkpankov
Jun 18 2015 14:58
ну на временный объект ты ссылаешься же
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 14:58
окей, тогда почему это работает?
fn get_vector() -> Vec<i32> {
    vec![1, 2, 3]
}

pub fn main() {
    let _len = get_vector().len();
    let _len2 = get_vector().iter().count();
}
ведь get_vector() тоже возвращает временный объект, разве нет?
Michael Pankov
@mkpankov
Jun 18 2015 15:00
на него ссылку никто не держит, len берёт её в том же операторе, а потом отпускает до ;, так что ссылка не переживает временный объект
и в _len2 тоже, ссылка умирает одновременно с объектом
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:01
так и в случае с кодом приведённым @lividgreen тоже никто не держит ссылку, все ссылки используются ровно до первой же ;
Michael Pankov
@mkpankov
Jun 18 2015 15:02
о каком коде @lividgreen мы сейчас говорим?
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:03
tail.clone().iter();
для простоты
Michael Pankov
@mkpankov
Jun 18 2015 15:03
@lividgreen я не уверен, что он этот кусок имеет ввиду
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:04
ну давайте на этом куске, чо
Michael Pankov
@mkpankov
Jun 18 2015 15:04
ну мне-то чо, пусть @madkinder скажет, где ему непонятно :)
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:04
ну мне не понятно немного, да
Michael Pankov
@mkpankov
Jun 18 2015 15:04
и тебе? ну ок
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:04
почему tail.clone().iter() не работает, хотя get_vector().len() работает по всей видимости
Michael Pankov
@mkpankov
Jun 18 2015 15:05
tail.clone() создаст временный объект, ссылку на который ты пытаешься сохранить в переменной. поэтому ссылка должна жить до конца блока. а временный объект раньше умрёт
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:05
мне кажется, что я интуитивно понимаю, и что я где-то читал/смотрел, как люди жаловались, что method syntax неочевидно работает в паре с lifetime ellision
но я пробовал гуглить и найти не могу
Michael Pankov
@mkpankov
Jun 18 2015 15:06
get_vector().len() возьмёт ссылку на этот вектор внутри len(), отпустит при выходе из len(), затем умрёт вектор
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:07
fn select<T>(v: &Vec<T>) -> Vec<T>{
    unreachable!()
}
fn main() {
    let tail = vec![1,2,3];
//    let tmp = select(&tail.clone());
//    let right = tmp.iter();
    let wrong = select(&tail.clone()).iter();
}
я об этом
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:07
ок, а так: get_vector().iter(); ?
будет работать по вашему, так, не запуская?
Michael Pankov
@mkpankov
Jun 18 2015 15:07
@lividgreen не будет работать
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:07
то же самое - результат вызова tail.clone() живёт ровно до первой же ;
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:08
почему с len() будет работать, а с iter() не будет? потому что iter() не отпускает ссылку?
Michael Pankov
@mkpankov
Jun 18 2015 15:08
@madkinder ага, а iter живёт до конца блока, и он держит &tail.clone()
@lividgreen да, у него внутри эта ссылка и она живёт столько же столько и структура
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:09
а, стоп-стоп, то есть если я сразу по этому итеру помаплю чё там мне надо, сделаю collect(), то всё в шоколаде будет?
Michael Pankov
@mkpankov
Jun 18 2015 15:09
@madkinder навскидку, да
@madkinder а если без collect(), то опять нет, я так думаю :D
надо посмотреть, но скорее всего так
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:10
ааа, ура же! мозаика сложилась :)
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:10
вот
теперь понятно
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:11
ну, я имел в виду любой consumer
Nick Palamarchuk
@lividgreen
Jun 18 2015 15:11
первая строчка работает, вторая нет
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:11
не обязательно именно collect - find тоже подойдёт
Michael Pankov
@mkpankov
Jun 18 2015 15:11
ну да. круто :)
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:11
ну всё, вселенная спасена, можно всё переписывать на расте :)
Michael Pankov
@mkpankov
Jun 18 2015 15:13
хехе
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:15
вообще, конечно, компилер шибко умный. однострочники с fold-ами в конце сворачивает в константу
был приятно удивлён
Michael Pankov
@mkpankov
Jun 18 2015 15:17
спасибо llvm за это
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:23
а есть возможность rustc/llvm попросить не создавать "ненужные" стековые кадры?
вот тут, например, можно не делать манипулиции с rbp и сэкономить 3 инструкции. в embedded это очень даже пригодилось бы
Michael Pankov
@mkpankov
Jun 18 2015 15:29
ну 3 инструкции это смех же, даже в embedded. если только такая функция вызывается в цикле 10610^6 раз :)
надо смотреть на проброс intrinsics, не уверен что сейчас можно легко это сделать
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:31
ни разу не смех
попривыкали тут, понимаешь ли!
в той же ATmega8, например, 1к озу
и лишние байты в стеке не нужны ни разу
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:32
да-да, для некоторых embedded - это rasbery pi :warning:
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:33
PI - это боинг же :)
Michael Pankov
@mkpankov
Jun 18 2015 15:33
это что мы, об экономии одного слова на стеке разговариваем?
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:33
да
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:33
в смысле, что каждые 268 дней падает, если не перегружать? :)
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:33
и возможности не писать на ассемблере
Michael Pankov
@mkpankov
Jun 18 2015 15:33
ну ладно, если вам оно надо.
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:34
так в Rust есть макрос для ассемблера
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:34
не, ну чё, если запихать рестарт сервиса в крон это ваш метод...
так а я не хочу писать на ассемблере :)
Michael Pankov
@mkpankov
Jun 18 2015 15:34
чем тут ассемблер поможет
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:34
в том-то и фишка, разве нет?
Michael Pankov
@mkpankov
Jun 18 2015 15:34
это пролог/эпилог
они в сях отключаются атрибутом bare, здесь такого нет вроде
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:34
я в курсе. но в данном случае он не нужен
Michael Pankov
@mkpankov
Jun 18 2015 15:34
(пока)
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:34
не, по крону - не тру. Тру - когда память дорастает до н мегабайт
Michael Pankov
@mkpankov
Jun 18 2015 15:35
я просто про то что inline assembly-то есть, но не поможет
@madkinder я бы кстати проверил, как это оптимизируется, когда это нормальная функция, а не main
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:35
если писать функцию целиком на асме, то поможет. но я ж так не хочу :)
Michael Pankov
@mkpankov
Jun 18 2015 15:36
у main могут быть ограничения, потому что это точка входа
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:36
@mkpankov без разницы, Rust не делает никаких предположений исходя из названий функций
qwe работает точно так же
Michael Pankov
@mkpankov
Jun 18 2015 15:40
какой-то чувак сказал что он пишет RFC для этого https://botbot.me/mozilla/rust/2015-06-18/?msg=42212975&page=11
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:42
круто, спасибо за инфу
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:43
о, пользуясь случаем. А каким irc клиентом пользуетесь?
Michael Pankov
@mkpankov
Jun 18 2015 15:43
у меня Empathy, ещё емаксовский erc
да здравстввует сломанный телефон :phone:
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:45
вообще-то хотелось бы, чтобы компилер автоматом выявлял, в каких функциях можно опускать пролог/эпилог
Michael Pankov
@mkpankov
Jun 18 2015 15:46
вроде это отладку затрудняет
Андрей Листочкин (Andrey Listochkin)
@listochkin
Jun 18 2015 15:46
ну я думаю, потом допилят
в релиз-билдах имхо уместно
Michael Pankov
@mkpankov
Jun 18 2015 15:46
а так-то llvm когда оптимизирует хвостовые вызовы, так и делаетс
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:46
я про релиз, конечно
отладку это не может затруднить, т.к. стековый кадр нужен только в случаях, если есть локальные переменные
и я говорил не про то, чтобы убрать весь пролог/эпилог, а именно про стековый кадр
Michael Pankov
@mkpankov
Jun 18 2015 15:48
ну и как ты поймешь без кадра что эта другая функция?
*это
отладчики стек разматывают просто ведь
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:48
что-то не понял вопроса
кто кого и куда разматывает? :)
Michael Pankov
@mkpankov
Jun 18 2015 15:49
без кадра стека нельзя понять, в какой функции ты находишься
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:49
при наличии отладочной информации отладчик знает, где какая локальная переменная в стеке
это ещё почему?
Michael Pankov
@mkpankov
Jun 18 2015 15:49
в той, которая позвала новую (но не создала кадра), или в самой новой
а, я понял, походу я налажал
надо ещё подумать
наверное ты прав
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:50
стековый кадр, это всего лишь запись текущего регистра базы (rbp), не более
Michael Pankov
@mkpankov
Jun 18 2015 15:51
да-да, у самой функции код-то другой, на ip посмотрим и поймем где мы
если она не само-рекурсивная, конечно
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:51
и нужен исключительно для того, чтобы было удобно адресовать переменные относительно неизменяемой базы (регистра rbp)
по rip действительно ничего не поймёшь
в режиме отладки в прологе функции в стековый кадр могут добавляться спец. метки, чтобы облегчить жизнь отладчику
Michael Pankov
@mkpankov
Jun 18 2015 15:53
почему ничего-то
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:53
чёт меня понесло :) в общем, пилят нужную фичу и хорошо
Michael Pankov
@mkpankov
Jun 18 2015 15:53
даже глупо если создать карту функций, от какого адреса до какого чей код идёт
проблемы с рекурсией, без неё будет работать
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:54
для рекурсивных, взаимно рекурсивных функций не сработает
Michael Pankov
@mkpankov
Jun 18 2015 15:54
о чём я и сказал
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 15:55
для всяких switch/case, которые реализуются jump table-ами, никто не гарантирует последовательность кода
это всё как компилятору вздумается, так и наэмитит :)
Michael Pankov
@mkpankov
Jun 18 2015 15:56
они всё равно локальными будут наверняка, а значит, у функций есть "границы"
Ihor Kaharlichenko
@kaharlichenko
Jun 18 2015 16:19
оказывается GCC тоже горазд так оптимайзить, правда у меня получилось только для С, для С++ уже не прокатило