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

    +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
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    93. 93
    94. 94
    95. 95
    96. 96
    97. 97
    #include <stdio.h>
    #include <stdlib.h>
    
    #define SPLICE(a,b) SPLICE_1(a,b)
    #define SPLICE_1(a,b) SPLICE_2(a,b)
    #define SPLICE_2(a,b) a##b
    
    
    #define PP_ARG_N( \
              _1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10, \
             _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
             _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
             _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
             _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
             _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
             _61, _62, _63, N, ...) N
    
    /* Note 63 is removed */
    #define PP_RSEQ_N()                                        \
             62, 61, 60,                                       \
             59, 58, 57, 56, 55, 54, 53, 52, 51, 50,           \
             49, 48, 47, 46, 45, 44, 43, 42, 41, 40,           \
             39, 38, 37, 36, 35, 34, 33, 32, 31, 30,           \
             29, 28, 27, 26, 25, 24, 23, 22, 21, 20,           \
             19, 18, 17, 16, 15, 14, 13, 12, 11, 10,           \
              9,  8,  7,  6,  5,  4,  3,  2,  1,  0
    
    #define PP_NARG_(...)    PP_ARG_N(__VA_ARGS__)    
    
    /* Note dummy first argument _ and ##__VA_ARGS__ instead of __VA_ARGS__ */
    #define PP_NARG(...)     PP_NARG_(_, ##__VA_ARGS__, PP_RSEQ_N())
    
    #define FIND_NONNULL_1(RES) \
      ((RES = (char *)(NULL)))
    
    #define FIND_NONNULL_2(RES, VAR) \
      ((RES = (char *)(VAR)))
    
    #define FIND_NONNULL_3(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_2(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_4(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_3(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_5(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_4(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_6(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_5(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_7(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_6(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_8(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_7(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_9(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_8(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_10(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_9(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_11(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_10(RES,__VA_ARGS__))
    
    #define FIND_NONNULL_12(RES, VAR, ...) \
      (((RES = (char *)(VAR)) != NULL)?RES:FIND_NONNULL_11(RES,__VA_ARGS__))
    
    // etc ...
    
    #define FIND_NONNULLS_(N, ...) \
      SPLICE(FIND_NONNULL_, N)(__VA_ARGS__)
    
    #define FIND_NONNULLS(...) \
    ({ \
      char *FIND_NONNULLS; \
      FIND_NONNULLS_(PP_NARG(FIND_NONNULLS, __VA_ARGS__), FIND_NONNULLS, __VA_ARGS__); \
      FIND_NONNULLS; \
    })
    
    char *side_effect_null(void)
    {
      printf("!!null!!\n");
      return NULL;
    }
    
    char *side_effect_test(void)
    {
      printf("!!test!!\n");
      return "test";
    }
    
    int main(void)
    {
      printf( "result:%s\n", FIND_NONNULLS(0,side_effect_null(),0,side_effect_test(),0,0,side_effect_test(),"govno", side_effect_test()) );
      return EXIT_SUCCESS;
    }

    Это типа как short-circuit evaluation чтоб по цепочке хрень возвращающую строку вызывать, и там те функции хуйпойми сколько аргументов могут принимать (но там может быть константа, тогда естественно нихрена не надо вызывать) пока оно не вернет не-NULL. Как только вернуло не-NULL то вернуть это и дальше ничего не вызывать, а то там сайд эффекты всякие ненужные будут. А если не-NULL так и не нашло, вернуть NULL

    Запостил: j123123, 09 Апреля 2021

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

    • Реализуемо ли это крестопарашной шаблонометушней без использования препроцессора?
      Ответить
      • Шоблоёбло полно по тьюрингу, так что ответ – да, в теории.

        Касательно перспектив осуществления этого на практике, лучше обратиться к Полине =^~^=
        Ответить
        • То что оно полно по Тьюрингу еще не означает, что любую петушню им можно сделать. Например, шаблоносранью нельзя никаким образом получить AST некоторого класса и синтезировать новый класс, в котором такой-то метод и такие-то члены класса теперь отсутствуют, и такие-то типы таких-то членов класса теперь другие и идут в другом порядке.
          Ответить
          • Поскольку шалабаны тюрингполны, ты можешь написать на них лексер и парсер, и построить AST же
            Ответить
            • А исходники читать через std::embed.
              Ответить
            • В принципе, на них потом можно это всё и скомпилировать. Итоговый бинарник, закодированный BASE-64 можно высрать в варнинге или онибке.
              Ответить
            • Только вот есть еще ограничения на то, что те шаблоны могут отрыгивать.
              Допустим, есть у тебя структура
              struct petuhi
              {
                int petuh;
                float plavuchi_petuh;
              };


              и допустим ты хочешь сделать структуру с переставленными первым и вторым полями, и приписать к ее названию слово "swap"
              struct petuhi_swap
              {
                float plavuchi_petuh;
                int petuh;
              };

              и чтоб это работало для произвольной структуры с произвольным набором аргументов (меняя при этом только положение первых двух полей), и делало структуру с именем, основанным на имени оригинала, приписывая в конце "_swap".

              Ну допустим ты передал в говношаблон тупо строку из исходника (опустим момент, как ты эту строку выковыривал):
              const char *shit =
              "struct petuhi\n"
              "{\n"
              "  int petuh;\n"
              "  float plavuchi_petuh;\n"
              "};\n"

              и это говно передаешь в шаблон
              И че с этим дальше делать? Он вообще умеет как-то читать строки? А может он умеет произвольную хуйню как бы вписать в исходник?
              Ну допустим можно взять констэкспр, и в компилтайме распарсить это говно и сделать компилтайм-строку с переставленной питушней, но как это вхуячить в исходник?
              Ответить
              • Как-то так это предлагалось делать в пропозале о метаклассах:
                constexpr {
                    for (const auto& field : compiletime_reverse(T$.fields)) {
                        -> { $field.type $field.name; }
                    }
                }
                Но я давно не следила, х.з. какой там прогресс сейчас.

                З.Ы. По-любому разрабы IDE уже плачут и пытаются отменить этот пропозал.
                Ответить
                • Давайте уже гомоиконность завезем, и вообще чтобы не было разницы между компайл таймом и рантаймом с точки зрения писания кода
                  Ответить
                  • Это так не работает. Сначала комитет примет 100500 частных случаев, посыпет их функциями Бесселя. И только потом начнёт обсуждать общий случай.

                    Там пи ещё не завезли, а ты уже гомоиконность хочешь...
                    Ответить
                    • Причём логичный, адекватный, внутренне непротиворечивый вариант не примут, потому что он не согласовывается с уже принятым частным случаем. Второй по адекватности не примут потому что противоречит другому частному случаю.
                      Ответить
                    • > Там пи ещё не завезли, а ты уже гомоиконность хочешь...

                      Наверное комитет не хочет завозить только pi. Надо еще и e завести. И почему только e и pi? Может завести вообще любые константы, ну чтоб например если мне понадобилась какая-то хуйня типа double myconst = sin(sqrt(pow(e, pi)) то чтоб у меня эта константа была с ммммммаксимально возможной точностью сгенерирована, чтоб там в компилтайме эта питушня делала вычисления с arbitrary-precision floating-point числами через какие-то ряды, и вписала мне самое точное приближение, которое можно хуйнуть в double.

                      Как долго комитет будет принимать такую поебень?
                      Ответить
                      • Надо еще чтоб гомоиконность генерить константы через численное интегрирование методом Монте-Карло в компилтайме, для этого надо чтоб ГПСЧ был в компилтайме с известным в компилтайме seed-ом, чтоб воспроизводимые сборки были.
                        Ответить
                        • Да сразу всю Maxima на constexpr'ы переписать, чтобы символьно диффуры решались. Т.к. Maxima на CL, заодно и гомоиконность подъедет.
                          Ответить
                        • Компайл-тайм ГПСЧ сидировать хэшем от __TIME__, чтобы веселее было!

                          Няпример: https://govnokod.ru/27287#comment617046.
                          Ответить
                          • > хэшем от __TIME__

                            Можно ещё кусок метушни зашифровать хешем от какой-нибудь даты в будущем.
                            Ответить
                      • Всё точно так! Ня данный момент предлагаемые константны выглядят так:
                        e - value of e
                        log2e - value of log2e
                        log10e - value of log10e
                        ln2 - value of ln2
                        ln10 - value of ln10
                        pi - value of π
                        inv_pi - value of 1/π
                        inv_sqrtpi - value of 1/√π
                        
                        sqrt2 - value of √2
                        
                        sqrt3 - value of √3
                        inv_sqrt3 - value of 1/√3
                        
                        egamma - value of Euler-Mascheroni γ constant
                        phi - value of golden ratio constant phi = (1+√5)/2
                        Ответить
                        • https://en.cppreference.com/w/cpp/numeric/constants - в C++20 они вроде как есть уже.

                          Только вот по какому принципу это все выбиралось? Почему inv_sqrt3 есть, но нет inv_sqrt2? Кому-то из стандартизаторов было очень нужно иметь 1/sqrt(3) как константу для какой-то математической хуйни, а вот 1/sqrt(2) ему не нужно было, и поэтому такой константы нет, или как это делается?
                          Ответить
                          • Да, так это и делается. Пишет кто-то proposal, где описывается что он хочет, нахуй это нужно, какие альтернативы есть и почему они — говно. И самое главное — дифф изменений к текущему стандарту. Это очень важно, потому что иначе на твой пропозал забьют хуй, если только кто-нибудь не захочет это всё прописать самостоятельно. Потом твою идею посылают нахуй, потому что она не стытуется с пунктом 13.1337.666.5, и ты выпускаешь следующию ревизию...

                            Например, пишет кто-то из Майкрософта предложение ввести константу 1,5, потому что у них много где она используется, и это было бы удобно. Оформляет это как надо, выносит на обсуждение. Там его забривают из Оракла, потому что они считают, что одной этой константы мало, а ещё нужно добавить '2', потому что они часто умножают на два. Потом подключается представитель ячейки программистов из Зимбабве и говорит, что им для денежных вычислений нужна константа '1000000000'. Все эти изменения вносятся, проходит голосование, всех устраивает, больше никому ничего не нужно, вносится в стандарт.

                            В результате, пи в стандарте не появляется, зато появляются охуенно нужные 1,5, 2 и 1000000000.
                            Ответить
                        • постоянной планки нет, крестобляди соснули
                          Ответить
          • > шаблоносранью нельзя

            Когда пропозал про метаклассы заедет -- можно будет.
            Ответить
      • В крестах всё хуёво с ленивыми вычислениями. Понадобится либо лямбда либо bind. Работать будет, но х.з. догадается ли конпелятор, что аргументы тут копировать не надо.
        Ответить
    • (s = side_effect_null()) || (s = side_effect_test()) || (s = "default";
      puts(s);


      Как-то так?
      Ответить
      • Да, типа этого. Только чтоб это удобнее записывалось через запятую без лишней питушни, и не делать временной переменной s.
        Ответить

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