1. Си / Говнокод #19766

    −45

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    printn(n,b) {
    	extern putchar;
    	auto a;
    
    	if(a=n/b) /* assignment, not test for equality */
    		printn(a, b); /* recursive */
    	putchar(n%b + '0');
    }

    в догонку к #19760. печатание числа `n` в base `b`. классический С образца 1972 года из UNIX v2. http://minnie.tuhs.org/cgi-bin/utree.pl?file=V2/lib/printf.c

    ЗЫ http://minnie.tuhs.org/cgi-bin/utree.pl?file=V2/lib - printf.c единственный С код в библиотеке был!

    ЗЗЫ это вам не энтерпрайз.

    Запостил: Dummy00001, 06 Апреля 2016

    Комментарии (80) RSS

    • Там ещё и на ассемблере всё... Ну конечно, сишка же тормозная. Особенно, если использовать её таким вот образом.

      Наверное, в те временя сишка воспринималась примерно как сейчас JS. Да и внешне даже немного похоже.
      Ответить
      • Так там же 1972й год, си только появился
        может быть они были как раз в процессе переписки с асма на си
        Ответить
      • высокоуровневые языки тогда уже /давно| существовали - лисп, фортран, алгол.

        но для полноценной утилизации ресурсов без асма было сложно.

        я думаю что проблема так же была что памяти было мало, софт стоил дорого, и специалисты тоже стоили дорого (потому что их было мало). почему разработка на асме была относительно дешевой.
        Ответить
        • писать ОС на лиспе достаточно сложно по очевидным причинам:)

          на ЯП высокого уровня писали всякую математику же

          си был именно что первым языком который с одной стороны достаточно low level, чтобы напрямую работать с памятью и пр, с другой -- переносим на уровне исходного кода (ради чего и был запилен собственно)
          Ответить
      • а вот это это - http://minnie.tuhs.org/cgi-bin/utree.pl?file=V2/c - к слову и есть первый С конпилятор.
        Ответить
    • > auto a;

      Я впервые вижу реальное использование авто. А если его убрать? Компилятор не сможет в одновременное implicit int и implicit automatic storage duration?
      Ответить
    • > auto a;
      Вывод типов.
      Ответить
      • auto auto a;

        обожаю переопределение одинаковых конструкций
        другой такой пример #import в objc и у Microsoft
        Ответить
    • > extern putchar;

      Наверняка ещё препроцессор и бесовские макросы вообще не используются и ни одного #include нет?
      Ответить
    • В плюсах только сейчас приходят к тому, чтобы не писать типы у аргументов/функций/переменных, а в си уже вон когда придумали.
      Ответить
      • да, это такой алгоритм вывода типов
        return int
        Ответить
        • как удобно! не надо больше читать длинных нудных мануалов по явному/неявному приведению/промоушн типов: int и готово. умели же аксакалы когда-то!
          Ответить
          • в классических сях же всё было charом или intом
            по умолчанию
            Ответить
            • В фортране/бейские автовывод получше будет.
              Ответить
              • Кстати, да.

                Пример из Бейсика:
                A% = 5
                B% = 3
                PRINT B%/A%

                Программа выводит 0.6, как и ожидалось.

                А теперь сраная сишка:
                int a = 5;
                int b = 3;
                printf("%f\n", b / a);


                Конпелируем и запускаем: http://ideone.com/ez38QA

                Выводит -0.592199. Откуда взялось это число???
                Ответить
                • а что за барсик такой у которого надо процент рисовать?

                  да, сишка ужасная
                  надо понимать что такое int, что такое float, ieee 754 вот еще голову забивать
                  Ответить
                  • В QBASIC были обозначения:
                    A% — целая переменная (аналог DIM A AS INTEGER, чтобы не рисовать процент, или DEFINT A, чтобы сделать все переменные на букву A целыми).
                    B& — длинная целая (DIM B AS LONG, DEFLNG B).
                    C! — вещественная (DIM C AS SINGLE, DEFSNG C).
                    D# — длинная вещественная (DIM D AS DOUBLE, DEFDBL D).
                    E$ — строковая (DIM E AS STRING, DEFSTR E).

                    Так что и в Бейсике приходилось забивать голову типами. Но в Бейсике почему-то из 3/5 автоматически выводился нужный тип, а в сишке нет.
                    Ответить
                    • Я вот помню тока что A это int, а A$ -- строка

                      видимо ты более лучше меня в бейские разбираешься
                      Ответить
                      • 10>DIM A(10)
                        Ответить
                      • От реализации Бейсика зависит. Знак доллара во всех означает строку, а другие знаки реализованы не во всех вариантах Бейсика.
                        Ответить
                        • я уже прочитал
                          много разных бейсиков есть на свете

                          хороший программист должен уметь все
                          и DONKEY.BAS
                          Ответить
                    • ну потому что иногда нужно именно целочисленное деление. И, когда оно нужно, оно нужно не в виде "приведи к даблам, посчитай и переведи обратно в целое".
                      Ответить
                      • ну на этот случай можно и в другую сторону слеш нарисовать.
                        Ответить
                • кстати странно, это ideone тупит, у меня считает корректно как целочисленное деление

                  http://coliru.stacked-crooked.com/a/a12c1809a617aa7d
                  Ответить
                  • Это все от архитектуры зависит (и не только, а еще от компилятора, соглашений вызова, фазы луны и проч). В gcc под x86-64 в линупсах оно вродекак на любой интовый аргумент вернет ноль
                    Ответить
                • >Выводит -0.592199. Откуда взялось это число???
                  от незнания сишечки, соглашений вызова в х86 и принтф-а, очевидно жэ. Там "%f\n" ожидает плавчуку, а не какой-то int, причем плавучку оно хочет получить в FPU говностеке, а т.к. мы передаем не плавучку а инт какой-то сраный, то в стек оно вообще не записывается. В стеке для плавучки лежит какая-то срань непонятная, вот она и выводится. При этом совершенно насрать на то говно, которое передается в printf в качестве второго аргумента. https://ideone.com/Jy0WcV
                  Ответить
                  • Ну вот, программист ещё должен знать, что́ именно в данный момент лежит в стеке FPU и что аргументы printf'а могут игнорироваться, если они помещаются не в FPU.

                    По внешнему виду вызова функции printf такое поведение вовсе не очевидно.
                    Ответить
                    • Программист должен знать, что не надо пихать в printf число типа int когда там стоит "%f\n". Остальные тонкости конечно ж тоже желательно знать, но они необязательны
                      Ответить
                      • Когда я пишу на Ассемблере, я управляю тем, через какие регистры у меня проходят данные, поэтому вопросов не возникает.

                        Когда я пишу на языках действительно высокого уровня, мне не приходится думать о регистрах, поэтому тоже вопросов не возникает.

                        А сишка — это кентавр наоборот, с человеческими ногами и с лошадиной головой. Она сочетает скорость человека с интеллектом коня. Т. е. управлять регистрами я не могу, но мне приходится о них думать.
                        Ответить
                        • -Дяденька, Вы кавалерист?
                          -Че, ноги кривые?
                          -Да нет. Рожа лошадиная!
                          Ответить
                        • >А сишка — это кентавр наоборот, с человеческими ногами и с лошадиной головой.
                          Что тогда представляют из себя плюсы? Там ведь тоже есть printf, и тоже будут такие вот проблемы, если в printf писать всякое говно
                          Ответить
                          • Смотря какие плюсы. Антикварные плюсы — это гибрид трёх языков: макросы + сишка + классы. Плюсы средних веков — это гибрид четырёх языков (добавились шаблоны — отдельный язык по сути). А новейшие плюсы — это гибрид пяти языков (добавилось вореционное исчисление лямбд).

                            Следующие плюсы будут похожи на PHP. Так вижу.

                            http://black-007.com/images/56b6d6ac2c964.jpg
                            Ответить
                            • > добавилось исчисление лямбд

                              о лямбда исчислении я знаю немногим больше чем то, что оно существует, но, разве оно имеет место быть в крестах?
                              Ответить
                            • Картинка хорошая, а про гибрид из языков - какая-то дичь.
                              Ответить
                              • > про гибрид из языков - какая-то дичь.

                                Вообще говоря, об этом даже Мейерс писал в Effective C++.
                                Item 1: View C++ as a federation of languages.
                                Ответить
                            • > (добавилось вореционное исчисление лямбд)
                              Что еще за исчисление лямбд? Туда просто добавили такой новый способ объявить анонимную функцию внутри функции, которая еще может захватывать какие-то там переменные. Ничего существенно нового эти лямбды не добавляют. Они там даже могут быть mutable т.е. изменять ту хрень, которая в них передана
                              Ответить
                              • Yo dawg so i heard you like functions so we put functions in your functions so you can create functions while you create functions
                                Ответить
                              • >>захва
                                ну так и пишите: кложи

                                а то лямбды, хуямбды
                                Ответить
                              • Принято. Пункт про лямбды вычёркиваем.

                                Тогда выручайте. Должно же что-нибудь быть в C++14, что не укладывается в стройную картину предыдущих крестов и при этом имеет самостоятельное значение.
                                Ответить
                                • constexpr?
                                  Ответить
                                  • "рекурсивные" вариадик темплейты.

                                    это блин какая-то функциональщина уже, блин.
                                    Ответить
                                    • > это блин какая-то функциональщина уже, блин.

                                      Шаблонное метапрограммирование испокон веков было функциональщиной без сборщика мусора. Поэтому его так легко понимать после haskell.
                                      Ответить
                                      • > без сборщика мусора
                                        Вот это и самое обидное - только начал метапрограммировать, а 16 гиг уже закончились...
                                        Ответить
                                      • я придумал!
                                        нужно встроить в язык AOP
                                        Ответить
                                • и еще асм вставки
                                  Ответить
                            • не понимаю почему кложи нужно считать за отдельный ЯП
                              Ответить
                            • следующего с++ не будет будет только php. На пхп будут писать все, драйвера, ОСи. Даже прошивки для микроконтроллеров будут писать на php в них будет встроен на аппаратном уровне апач и mysql.
                              Ответить
                            • >Следующие плюсы будут похожи на PHP. Так вижу.

                              Я об этом уже который год говорю.

                              Спасибо некромантам за оживление годного треда. Методично проставил @ inkanus-gray плюсы.
                              Ответить
                          • >Что тогда представляют из себя плюсы?
                            Франкенштейна же.

                            http://www.simpsoncrazy.com/content/pictures/onetimers/FrinkSr.gif
                            Ответить
                            • > плюсы? Франкенштейн

                              https://m.reddit.com/r/cpp/comments/4pmlpz/what_the_iso_c_committee_added_to_the_c1 7_working/
                              Ответить
                    • так бывает, что программисту нужно что-то знать. Тяжело быть программистом.
                      Ответить
                      • Да, бывает. Однако, быть программистом на Malbolge и на Брейнфаке никто не заставляет, когда есть языки с более очевидным синтаксисом.
                        Ответить
                  • а почему ты считаешь что это число не попадает в стек FPU?
                    я вот думаю что он честно делает fld или как там его, просто туда попадает int, чье представление немного отлично от float
                    Ответить
                    • Ну ты там посмотри ассемблерный выхлоп, соглашения вызова конкретного компилятора на конкретной платформе, и сразу ясно будет
                      Ответить
                    • Вот такая хрень получается:

                      #include <stdio.h>
                       
                      int test1(void)
                      {
                        printf("%f\n", 1.0);
                        return 0;
                      }
                      
                      int test2(void)
                      {
                        printf("%f\n", 1);
                        return 0;
                      }


                      gcc -O2 -m32 -S test.c

                      .LC1:
                              .string "%f\n"
                              .text
                              .p2align 4,,15
                              .globl  test1
                              .type   test1, @function
                      test1:
                      .LFB24:
                              .cfi_startproc
                              subl    $28, %esp
                              .cfi_def_cfa_offset 32
                              fld1  # <--- загрузить константу 1. в говностек для плавучки http://www.club155.ru/x86cmdfpu/FLD1
                              fstpl   8(%esp) # <--- пропихнуть хрень из говноплавучего стека в обычный http://www.club155.ru/x86cmdfpu/FSTP
                              movl    $.LC1, 4(%esp) # <--- загрузить указатель на "%f\n" в стек
                              movl    $1, (%esp)
                              call    __printf_chk
                              xorl    %eax, %eax
                              addl    $28, %esp
                              .cfi_def_cfa_offset 4
                              ret
                              .cfi_endproc
                      .LFE24:
                              .size   test1, .-test1
                              .p2align 4,,15
                              .globl  test2
                              .type   test2, @function
                      test2:
                      .LFB25:
                              .cfi_startproc
                              subl    $28, %esp
                              .cfi_def_cfa_offset 32
                              movl    $1, 8(%esp) # <--- загрузить 1 сразу в обычный стек, а не этот говнорегистровый стек
                              movl    $.LC1, 4(%esp) # <--- загрузить указатель на "%f\n" в стек
                              movl    $1, (%esp)
                              call    __printf_chk
                              xorl    %eax, %eax
                              addl    $28, %esp
                              .cfi_def_cfa_offset 4
                              ret
                              .cfi_endproc
                      Ответить
                      • а почему в стек грузят через мов есп а не пуш?
                        Ответить
                        • Думаю это связано с тем, что так быстрее
                          Ответить
                          • и где EBP? там чтоли фрейм поинтер имит случилсо?
                            Ответить
                            • > и где EBP
                              А зачем целый регистр тратить на нахуй никому не нужный фреймпоинтер?
                              Ответить
                              • чтобы потом без символов раскручивать стек
                                известно же зачем
                                Ответить
                                • > без символов
                                  Кому это надо кроме реверсеров? Да и та же IDA вполне умеет трекать переменные по ESP.
                                  Ответить
                                  • а как она умеет? как найти указатель на вызывающую функцию без frameptr?
                                    Ответить
                                    • > как найти указатель на вызывающую функцию без frameptr
                                      По ret'у же. Конпелятор никуда не денется, всё лишнее уберёт перед ret'ом.

                                      Ну или по точке входа, когда esp ещё никуда уплыть не успел.

                                      Олсо, у её анализатора таки крышу сносит, если прога делает какие-нибудь непонятные трюки с esp посреди функции.
                                      Ответить
                                      • по рету это надо весь код анализировать

                                        а с ебп там был просто лист же
                                        Ответить
                                        • А кто сказал, что будет легко? :)

                                          Ну и отладка без символов - имхо, не самый приоритетный кейс. А вот лишний регистр на x86, где их не так уж много, весьма ценен.
                                          Ответить
                                          • особенно в x64, ггг
                                            Ответить
                                            • > x64
                                              Да даже на amd64, где регистров побольше, этот фреймпоинтер только зря будет такты жрать на входе и выходе процедуры...
                                              Ответить
                                              • ну мс примерно так и думало когда собирало винду без него

                                                но с висты уже собирает с ним
                                                и линксы тоже
                                                Ответить
                    • Казалось бы, логично было бы предположить, что __printf_chk будет брать хуйню из обычного стека, а не говноплавучего.
                      Но хуй там https://paste.debian.net/hidden/0a0b3ee3/
                      Как можно видеть из этого говнопримера (тестировалось это говно на Ubuntu 14.04.4 LTS 64bit с дефолным gcc) этому __printf_chk насрать на хуйню, записанную в обычный стек, когда оно хочет вывести плавучку. Несмотря на то, что плавучее говно пишется и в обычный стек, оно его все равно берет из плавучего стека. И таким образом, этот test1.с выводит на оба случая число 1.000000 т.к. после функци test1() в стеке осталось насрано числом 1.000000, а test2() просто находит в стеке это говно и выводит его. А в случае test2.с в стеке насрано чем-то другим, и функция test2() запускается первее, каждый раз выводит какое-то новое случайное говно, которое оказалось в говноплавучем стеке
                      Ответить
                      • может быть какая-то гнутая оптимизация.

                        не стоит забывать что это специальный случай: передача параметров в va-args функцию.

                        *ABI для i386 под рукой нет.*

                        я слышал что там была новая версия ABI, так как народ решил забить на поддержку оригинальных i386-i586 процов. может быть там что-то поменялось.

                        ЗЫ не уверен что это оно - https://01.org/sites/default/files/file_attach/intel386-psabi-1.0.pdf - но похоже на это. капипаста из оригинального http://www.sco.com/developers/devspecs/abi386-4.pdf которая ничего не говорит. (даже то что типы промотятся не говорится. мля.)
                        Ответить
    • O(log(b, n)), оптимизировано!
      Ответить
      • Ну так быстрее всё равно число напечатать невозможно, а медленнее - надо очень постараться.
        Ответить
    • ГДЕ ЗДЕСЬ C????
      https://en.wikipedia.org/wiki/B_%28programming_language%29
      Ответить
      • +1. другими словами K&R не изобрели С - они просто B сплагиатили.
        Ответить

    Добавить комментарий