Няшная / Говнокод #19766 Ссылка на оригинал

0

  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 Dummy00001, (Updated )

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

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

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

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

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

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

        си был именно что первым языком который с одной стороны достаточно low level, чтобы напрямую работать с памятью и пр, с другой -- переносим на уровне исходного кода (ради чего и был запилен собственно)
        Ответить
  • > auto a;

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

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

    Наверняка ещё препроцессор и бесовские макросы вообще не используются и ни одного #include нет?
    Ответить
  • В плюсах только сейчас приходят к тому, чтобы не писать типы у аргументов/функций/переменных, а в си уже вон когда придумали.
    Ответить
      • как удобно! не надо больше читать длинных нудных мануалов по явному/неявному приведению/промоушн типов: 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$ -- строка

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

                        хороший программист должен уметь все
                        и DONKEY.BAS
                        Ответить
                  • ну потому что иногда нужно именно целочисленное деление. И, когда оно нужно, оно нужно не в виде "приведи к даблам, посчитай и переведи обратно в целое".
                    Ответить
                    • ну на этот случай можно и в другую сторону слеш нарисовать.
                      Ответить
                • Это все от архитектуры зависит (и не только, а еще от компилятора, соглашений вызова, фазы луны и проч). В 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, что не укладывается в стройную картину предыдущих крестов и при этом имеет самостоятельное значение.
                              Ответить
                                • "рекурсивные" вариадик темплейты.

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

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

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

                            Спасибо некромантам за оживление годного треда. Методично проставил @ inkanus-gray плюсы.
                            Ответить
                  • так бывает, что программисту нужно что-то знать. Тяжело быть программистом.
                    Ответить
                    • Да, бывает. Однако, быть программистом на 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
                                            Да даже на 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 которая ничего не говорит. (даже то что типы промотятся не говорится. мля.)
                      Ответить
    • Ну так быстрее всё равно число напечатать невозможно, а медленнее - надо очень постараться.
      Ответить
    • +1. другими словами K&R не изобрели С - они просто B сплагиатили.
      Ответить

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

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8