темные закоулки языка C
Mar. 9th, 2013 02:48 pmSome dark corners of C
Набор забавных малоизвестных особенностей C. Самый интересный пример там, на мой взгляд - следующие две функции:
Если хотите - подумайте сами, почему компилятор генерирует более эффективный код для второй из них, foo2, перед тем, как прочитать ответ.
Правильный ответ:в первом случае компилятор не может исключить возможность того, что x==z.
Я также не знал, что в C99 есть ключевое слово restrict, которое решает эту проблему.
Набор забавных малоизвестных особенностей C. Самый интересный пример там, на мой взгляд - следующие две функции:
void foo1(int *x, int *y, int *z) {
*x += *z;
*y += *z;
}
void foo2(int *x, int *y, int *z) {
int w = *z;
*x += w;
*y += w;
}
Если хотите - подумайте сами, почему компилятор генерирует более эффективный код для второй из них, foo2, перед тем, как прочитать ответ.
Правильный ответ:
Я также не знал, что в C99 есть ключевое слово restrict, которое решает эту проблему.
no subject
Date: 2013-03-09 12:53 pm (UTC)no subject
Date: 2013-03-09 12:57 pm (UTC)Ну и вообще - анти-интуитивные вещи забываются или не приходят на ум. Программист знает, что конечно же x!=z, и для того, чтобы помнить, что компилятор об этом не знает, нужна ментальная дисциплина. Скажу про себя: я хорошо знаю об этой проблеме теоретически, даже сталкивался с ней раз или два практически, оптимизируя какой-то код (очень давно), и все равно во время чтения этой презентации заново удивился.
no subject
Date: 2013-03-09 01:15 pm (UTC)In any case, both examples show a somewhat defective C code that I would not pass on a code review. When *z is not intended to be modified, I would insist that it is marked as const. I do wonder if that const would cause the compiler to assume no aliasing. Something I may want to try...
no subject
Date: 2013-03-09 01:22 pm (UTC)no subject
Date: 2013-03-09 01:25 pm (UTC)no subject
Date: 2013-03-09 01:31 pm (UTC)no subject
Date: 2013-03-09 01:32 pm (UTC)no subject
Date: 2013-03-09 01:48 pm (UTC)Нужна оговорка, "обычно генерирует" :) У меня тут вчера было волшебство - "менее эффективный" код с assert-тами работает быстрее чем оптимизированная версия без них. http://users.livejournal.com/_winnie/379152.html
no subject
Date: 2013-03-09 02:06 pm (UTC)no subject
Date: 2013-03-09 02:20 pm (UTC)ld hl,screen_addr
ld de,screen_addr+1
ld bc,6143
ld (hl),0
ldir
Команда ldir копирует bc байт информации, начинающейся с адреса hl, в блок памяти, начинающийся с адреса de. С учётом выбранных адресов, 0 вручную пишется в первый байт, а затем копируется из первого во второй, из второго в третий, и т.д. Экран очищается по индукции.
Про ещё более быстрый способ очистки экрана я лучше рассказывать не буду.
no subject
Date: 2013-03-09 02:24 pm (UTC)no subject
Date: 2013-03-09 02:31 pm (UTC)no subject
Date: 2013-03-09 02:40 pm (UTC)no subject
Date: 2013-03-09 04:13 pm (UTC)no subject
Date: 2013-03-09 04:31 pm (UTC)no subject
Date: 2013-03-09 04:40 pm (UTC)no subject
Date: 2013-03-09 05:07 pm (UTC)причем не все из них вошли в C++, даже 11.
no subject
Date: 2013-03-09 05:29 pm (UTC)no subject
Date: 2013-03-09 05:30 pm (UTC)no subject
Date: 2013-03-09 05:32 pm (UTC)http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank
no subject
Date: 2013-03-09 05:48 pm (UTC)no subject
Date: 2013-03-09 05:58 pm (UTC)void foo(int *x, int *y, const int *z) {
*x += *z;
*y += *z;
}
int xx = 3, yy = 4;
void bar()
{
foo(&xx, &yy, &xx);
}
Что говорит Стандарт по этому поводу?
no subject
Date: 2013-03-09 06:12 pm (UTC)Гавно
Date: 2013-03-09 07:18 pm (UTC)Спасибо за откровенность.
Я с этим согласен. Например, найдите картинку в Гугле "Одноногий мужик в шляпе" и посмотрите сто первых результатов. Сразу видно достижения функционального программирования и прочего компьютерсаенс: полное гавно.
no subject
Date: 2013-03-09 08:58 pm (UTC)А Вы знаете про strict aliasing?
Благодаря нему поведение вот такого вот кода (вполне невинно выглядящего на первый взгляд) неопределено (http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html):
uint32_t swap_words( uint32_t arg ) { uint16_t* const sp = (uint16_t*)&arg; uint16_t hi = sp[0]; uint16_t lo = sp[1]; sp[1] = hi; sp[0] = lo; return (arg); }no subject
Date: 2013-03-09 09:15 pm (UTC)no subject
Date: 2013-03-09 09:20 pm (UTC)Если программист, хотел сделать то, что делает фу2 и при этом он написал фу1, то это просто баг потому, что в случаях, когда x==y эти функции ведут себя по разному. Меньшая эффективность тут как раз наименьшая из возможных проблем.
no subject
Date: 2013-03-09 09:44 pm (UTC)no subject
Date: 2013-03-09 09:47 pm (UTC)+100500
А в общем случае - фиг знает что и как соптимизирует компилятор, и подгонять код под оптимизацию конкретной версии конкретного компилятора - извращение.
no subject
Date: 2013-03-10 02:01 am (UTC)no subject
Date: 2013-03-10 08:14 am (UTC)no subject
Date: 2013-03-10 08:18 am (UTC)no subject
Date: 2013-03-10 08:44 am (UTC)no subject
Date: 2013-03-10 09:26 am (UTC)Не сильнее const - если бы у потока не было оператора для const char*, а только для char*, та же ситуация бы была, нет?
no subject
Date: 2013-03-10 09:27 am (UTC)Другой вопрос, что к оптимизации надо подходить грамотно, сначала делая профайлинг.
no subject
Date: 2013-03-10 09:27 am (UTC)no subject
Date: 2013-03-10 09:31 am (UTC)С99 вообще странно существует - почти как f77, f90 и т.д.
no subject
Date: 2013-03-10 09:48 am (UTC)no subject
Date: 2013-03-10 10:05 am (UTC)no subject
Date: 2013-03-10 03:19 pm (UTC)no subject
Date: 2013-03-10 03:20 pm (UTC)no subject
Date: 2013-03-10 04:36 pm (UTC)no subject
Date: 2013-03-10 04:54 pm (UTC)Другой вопрос, что, опять-таки, для меня основной критерий — это не тупость компилятора, а "некрасиво".
no subject
Date: 2013-03-10 09:44 pm (UTC)no subject
Date: 2013-03-11 06:15 am (UTC)