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

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    #include <stdio.h>
    //#include <ynopoTocTb.h>
    
    #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
    #define CAT(...) PRIMITIVE_CAT(__VA_ARGS__)
    
    #define EAT(...)
    #define EXPAND(...) __VA_ARGS__
    #define IIF(c) PRIMITIVE_CAT(IIF_, c)
    #define IIF_1(...) __VA_ARGS__ EAT
    #define IIF_0(...) EXPAND
    
    #define COMPL(x) PRIMITIVE_CAT(COMPL_, x)
    #define COMPL_1 0
    #define COMPL_0 1
    
    #define CHECK_N(x, n, ...) n
    #define CHECK(...) CHECK_N(__VA_ARGS__, 0)
    #define PROBE(x) x, 1
    
    #define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x))
    #define NOT_0 PROBE(~)
    #define BOOL(x) COMPL(NOT(x))
    
    #define IF(c) IIF(BOOL(c))
    
    #define EMPTY()
    #define DEFER(id) id EMPTY()
    #define OBSTRUCT(id) id DEFER(EMPTY)()
    
    #define  EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
    #define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
    #define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
    #define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
    #define EVAL4(...) EVAL5(EVAL5(EVAL5(EVAL5(__VA_ARGS__))))
    #define EVAL5(...) __VA_ARGS__
    
    #define DEC(x) PRIMITIVE_CAT(DEC_, x)
    #define DEC_0 0
    #define DEC_1 0
    #define DEC_2 1
    #define DEC_3 2
    #define DEC_4 3
    #define DEC_5 4
    #define DEC_6 5
    #define DEC_7 6
    #define DEC_8 7
    #define DEC_9 8
    
    #define FACTORIAL(x) \
      IF(NOT(x)) (1) \
      ( \
        OBSTRUCT(FACTORIAL_INDIRECT)()(DEC(x)) * x \
      )
    
    #define FACTORIAL_INDIRECT() FACTORIAL
    
    #define PRIMITIVE_TO_STR(...) # __VA_ARGS__
    #define TO_STR(...) PRIMITIVE_TO_STR(__VA_ARGS__)
    
    int main() {
        printf("7! = " TO_STR(EVAL(FACTORIAL(7))) " = %d", EVAL(FACTORIAL(7)));
        return 0;
    }

    Продолжаю макроёбить.
    https://ideone.com/WcG7i2

    Использованы материалы из стотьи
    https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms

    Запостил: adrnin, 01 Ноября 2018

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

    • #мокро-макро
      Ответить
    • Кстать, форичь на мокросах:
      #define IS_EMPTY(x) CHECK(PRIMITIVE_CAT(IS_EMPTY_, x))
      #define IS_EMPTY_ PROBE(~)
      
      #define FOREACH(macro, x, ...) \
        IF(IS_EMPTY(x)) \
        ( \
          /*stop*/ \
        ) \
        ( \
          macro(x) \
          OBSTRUCT(FOREACH_INDIRECT)()(macro, __VA_ARGS__) \
        )
      #define FOREACH_INDIRECT(...) FOREACH
      
      /*  использование  */
      
      puts(EVAL(FOREACH(TO_STR, 0, 1, 2, 3, 4)));
      Ответить
      • ( \
            /*stop*/ \
          ) \
          ( \

        в этом месте уже понятно что пора бы остановится
        Ответить
        • Только щас понел, что на пенис похоже...
          Ответить
    • Гуры, поясните нубу что происходит со стеком в момент поимки исключения в крстах. До какого места он раскручивается?

      int g = 100;
      try {
      int i = 42;
      throw Foo;
      } catch(Foo f) {
      //виден-ли тут i?
      // если да, то как? это же другой блок!
      // а если нет, то почему Foo виден? Или Foo копируется?
      //g-то стопудово виден?
      }

      сложные вашы плюсы, setjmp/longjmp куда прощше
      Ответить
      • Ты внятно пиши, что ты хочешь

        > виден-ли тут i?
        Нет.

        > а если нет, то почему Foo виден?

        Foo это тип? почему его должно быть не видно?

        > Foo копируется?

        Да. Надо писать
        catch (const Foo& foo)

        А вообще объекты, брошенные через throw, живут не на стеке. Поэтому размотка стека на них не влияет.
        Ответить
        • >>Foo это тип? почему его должно быть не видно?
          Я имел ввиду объект, он же создается ниже i. Но если он копируется то понятно.

          >>catch (const Foo& foo)
          Опять непонятно: мне передается ссылка на foo? А где сам foo живет?

          Ладно, спасибо, видимо надо RTFM читать
          Ответить
          • > Но если он копируется то понятно.

            Не обязательно копируется. Это ты сам попросил копию в catch. Скорее всего, throw сам вызывает конструктор на заранее подготовленном участке памяти.

            > А где сам foo живет?

            Стандарт не скажет тебе явно, где. Но очевидно, что не на стеке, поэтому всё и работает.
            Ответить
            • Все, понял.

              Значит, стандарт говорит что когда я пишу

              throw Foo я создаю "где-то" объект класса Foo, и он доступен в момент catch.
              А удалять его вручную не надо, да?
              Ответить
        • >> брошенные через throw, живут не на стеке
          да? а где? в куче? или в "специальном месте" (как сказал Elvenfighter)?

          Я же пишу trhow Petux, а не throw new Petux
          Ответить
          • > throw new Petux

            Такое тоже можно написать, но тогда удалять надо после поимки. Так делать не надо.
            Ответить
            • >>но тогда удалять надо после поимки
              catch (Petux& p) {
              delete p;
              }
              ?

              А вот так ведь тоже можно:
              Foo foo;
              throw foo;

              Выходит что foo сначала скопируется, а затем старый удалится (и вызовется десктруктор!)
              воу
              Ответить
              • > catch (Petux& p) {
                delete p;
                }

                Подозреваю, что так не поймается, проверь. Удалять по ссылке тоже нельзя.

                Ты же кинул указатель, ловить нужно тоже указатель.

                catch (const Petux * const p) {
                // петухам тут не место.
                delete p;
                }
                Ответить
                • Мне казалось что ссылку можно рассматривать как константый указатель который автоматически разыменовывается, но может быть компилятор так не думает))

                  Спасибо, проверю
                  Ответить
                  • Понятие сцылки, укозателя, разуменовани, если не ошибаюсь, есть только на уровне языка, на уровне машкода есть только адреса, регистры, только хардкор.
                    Ответить
                    • Разумеется

                      ты или кладешь в регистр или 42 или данные по адресу 42
                      Все
                      ссылки-хуилки ему параллельно
                      Ответить
                • Я проверил, ты прав.

                  Вообще я раскурил это говно: есть даже золотое правило "Throw by value, catch by reference" http://ptgmedia.pearsoncmg.com/images/0321113586/items/sutter_item73.pdf

                  И у шланга есть ворнинги на случай его нарушения)

                  Если кинуть анонимный exception (throw Foo()) то он сразу создастся в месте, доступном из catch, и если поймать его по референсу, то референс в catch и придет а при выходе из catch он удалится.

                  Если поймать по значению, то он туда скопируется (во всыком случае в VC++) -- вызовится копирующий конструктор.

                  Если создать на стеке (Foo f; throw f;) то он скопируется со стека в то самое место, откуда его видно из catch.

                  Самый треш это кинуть создав на стеке и поймать по значению: скопируется 2 раза!
                  Ответить
    • > // а если нет, то почему Foo виден? Или Foo копируется?
      Осмелюсь предположить, что (тип) Foo был обьявлен где-то выше. Потому и доступен.

      > } catch(Foo f) {
      А вот тут ты копируешь себе `Foo f`.

      Не знаю, как именно, но выбрасываемое значение записывается в специальное место, чтоб `catch` (и std::current_exception) мог это значение достать.
      https://en.cppreference.com/w/cpp/error/current_exception
      Ответить
      • >>тип
        я имел ввиду объект)

        >>А вот тут ты копируешь себе `Foo f`.
        >>специальное место
        ага, значит не стек
        Ответить
    • Православный сишкотред окккупировали крестоносцы... Негоже!
      Ответить
    • Вообще, как я щетаю, бьярн строусьруп не осили макро си и поэтому придумал себе сипюлспюлс с классами, шоблонами, бледжеками и шлюхой.
      Ответить
      • Я сомневаюсь в том, что шаблоны придумал Страуструп. В первой версии стандарта их не было. Они появились только в начале 90-х.
        Ответить
        • Я понятие не имею, есть же мокрлсы, засем шоьлоны?
          Ответить
          • Ну типа чтобы обойтись без препроцессора. Хотя в итоге препроцессор так и оставили...
            Ответить
            • А ещё это... когда делаешь что-то не препроцессором, а встроенными средствами языка, компилятор может выполнить дополнительные проверки и вывести полезные диагностические сообщения. Уже ржу, вспомнив, что выводят популярные компиляторы при сборке программы, использующей STL или другие библиотеки.

              P.S. Вдруг кому-то пригодится:
              https://www.bdsoft.com/tools/stlfilt.html
              Ответить
          • Вообще, если я правильно понял, когда изобретали шаблоны, в других языках (в языке Ада, например) уже были дженерики, поэтому появилось желание «сделать как у всех». Однако, дженерики создают один экземпляр кода с проверкой типа в рантайме. Крестовики решили, что это анскилльно и снижает пирфоманс, поэтому решили всё перенести в компайлтайм. Крестошаблоны создают несколько копий кода, каждый из которых заточен под определённый тип. Т. е. в крестах выбор типа производится статически, поэтому пирфоманс не падает (правда, ценой распухания кода).
            Ответить
            • > правда, ценой распухания кода
              Ну смотря как метушить. Небольшие шаблоны удаётся заинлайнить и от них остаётся пара-тройка инструкций... Чего не скажешь об операторе сдвига в поток.
              Ответить
          • мокросы не тайпсейф
            Ответить
    • А вот еще вопрос
      я правильно понимаю что например
      const int petux = 42;
      скорее всего заинлайнится и не будет отличимо от #define PETIX 42

      ?

      но вот если я скажу
      int* a = &petux; (например штобы передать ссылку в шаблон) то сразу же вся инлайноптитмизация пойдет лесом?
      Ответить
      • > скорее всего заинлайнится
        Да.

        > то сразу же вся инлайноптитмизация пойдет лесом
        Нет. Иногда и так справляется.
        Ответить
        • >>нет
          но как?

          временной переменной?
          а если я возвращаю адрес


          зы: заметил что люди много и с большим удовольствием говорят при сишечку и плюсы, куда активнее чем про другие языки
          Ответить
    • >>Unfortunately, macros can't expand recursively.
      а шаблоны могут

      Слушайте, а шаблоны же если тюрингполны то для них актуальна хальтинг проблем?
      Реально написать программу которая не скомпилируется никогда?
      Ответить
      • Не, память не бесконечная. Конпелятор упадёт.
        Ответить
        • Надо в шаблоны добавить GC
          И корутины еще чтобы удобнее было параллелить процесс компиляции
          Ответить
          • Недавно обсуждали профайлеры и дебагеры для компайл-тайм.

            Не могу найти обсуждение. Помню шутки вроде «Программа медленно компилируется. Отладь». Ещё вроде ссылка была на Х-р.
            Ответить
            • >>ссылка была на Х-р.
              на хер??
              Ответить
            • В "PHP" никто не знает про компиляцию, дебагеры и профайлеры.
              И потому я
              Ответить
              • Я знаю. Я устанавливал "xcache", "xdebug" и "xhprof".
                Ответить
                • Ты не репрезентативен

                  Давай спросим КитКата Овена?

                  ОВЕН, ты используешь дебагер и профайлер?
                  Ответить
                  • Нет. В крайних случаях мне хватает временного отключения вывода ошибок в "PHP" и "EXPLAIN" в "MySQL". Автоматические тесты, смысл которых мне до сих пор неясен я также не использую.
                    Ответить
    • Тоже когда-то занимался макроебством. Для рекурсии использовал вложенные инклуды и __INCLUDE_LEVEL__
      // pow.h
      #ifndef OUT_V
          #error "OUT_V not defined!"
      #endif
      
      #ifndef IN_X
          #error "IN_X not defined!"
      #endif
      
      #ifndef IN_Y
          #error "IN_Y not defined!"
      #endif
      
      
      #if(IN_Y == 0)
          OUT_V = 1;
      #elif( IN_Y == 1)
          OUT_V = IN_X;
      #elif(__INCLUDE_LEVEL__ == 1)
          OUT_V = IN_X *
          #include "pow.h"
      #elif(IN_Y > __INCLUDE_LEVEL__)
          IN_X *
          #include "pow.h"
      #else
          IN_X;
      #endif


      //main.c
      int main(){
      
          int v;
          double f;
          #define OUT_V v
          #define IN_X 4
          #define IN_Y 4
          #include "pow.h"
          printf("v: %d\n",v );
      
          #define OUT_V f
          #define IN_X 1.41421356
          #define IN_Y 4
          #include "pow.h"
          printf("f: %f\n",f );
      
          #define OUT_V f
          #define IN_X 10.0
          #define IN_Y 100
          #include "pow.h"
          printf("f: %E\n",f );
          return 0;
      }
      Ответить
    • Как на мокросах числа ымулировать? Вот таким методом хорошо получаются INC, DEC, ADD:
      #define INC(...) __VA_ARGS__,@
      
      #define DEC_PRIMITIVE(x, ...) __VA_ARGS__
      
      #define DEC(...) DEC_PRIMITIVE(__VA_ARGS__)
      
      #define EXPAND(...) __VA_ARGS__
      
      #define ADD(...) __VA_ARGS__,EXPAND
      
      #define TO_C_NUMBER(...) (sizeof(TO_STR(__VA_ARGS__)) / 2)
      
      #define TO_STR(...) TO_STR_PRIMITIVE(__VA_ARGS__)
      
      #define TOSTR_PRIMITIVE(...) # __VA_ARGS__
      С остальным пролбемы.
      Ответить

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