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

    +3

    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
    #include <stdio.h>
    #include <stdlib.h>
    
    #define DEREF(x) ({*(x);})
    #define PTR(x) ({&(x);})
    #define PTR_T(x) typeof(typeof(x) *)
    #define DEREF_T(x) typeof( ({typeof(x) DEREF_T; *DEREF_T;}) )
    
    
    void add5(PTR_T(int) a)
    {
      DEREF(a)+= 5;
    }
    
    int main(void)
    {
      int a = 0;
      printf("%d\n", a);
      add5(PTR(a));
      printf("%d\n", a);
      
      int b = 5;
      PTR_T(b) b_p = PTR(b); // int *
      printf("%d\n", DEREF(b_p) );
      
      DEREF_T(b_p) c = 666; // int
      printf("%d", c);
      
      return EXIT_SUCCESS;
    }

    https://govnokod.ru/27476#comment637183

    ASD_77:
    потому что я люблю Си и С++ но ненажижу * и & ... поэтому я решил исправить этот недочет в мире

    Исправил, проверь. Компилится только в GCC, всё-таки Clang не 100% совместим c гнутыми расширениями.

    Запостил: j123123, 21 Июня 2021

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

    • Кстати, я когда-то и пародию на крестопарашный auto делал на такой хуйне.

      #define ASSIGN_AUTO(var_name, value) typeof(value) var_name = value;
      Ответить
    • А зачем фигурные скобки в дерефе?
      Ответить
      • Это https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
        Да, эти макросы можно так переписать
        #define DEREF(x) (*(x))
        #define PTR(x) (&(x))
        , и тогда это и в Clang соберется
        А вот
        #define DEREF_T(x) typeof( ({typeof(x) DEREF_T; *DEREF_T;}) )

        не очень ясно как переписать без фигурных скобок.
        Ответить
        • typeof(*(typeof(x))NULL)
          Ответить
          • Да, так тоже можно. А не будет ли там UB из-за этого разыменования нуля?

            #define DEREF_T(x) typeof( ({typeof(x) DEREF_T; typeof(*DEREF_T) TMP; TMP;}) )

            Вот тут разыменования нуля быть не должно
            Ответить
            • > не будет ли там UB

              Х.з., я не думаю, что конпеляторы настолько злые, что что-то оптимизируют внутри typeof или sizeof...

              З.Ы. Ну разадресуй единичку, чтобы даже формально не доебались.
              Ответить
              • Хотя с единичкой ему ещё выравнивание не понравится. Пиздец, а не язык, конечно.
                Ответить
      • Да, с точки зрения GCC, если есть хуйня
        int a = 5;
        ({a;}) = 6;

        То ({a;}) это lvalue и оно нормально присваивает.
        Clang же не считает такую хрень валидной:
        error: expression is not assignable
        Ответить
    • а можно вот тоже самое только без define и на уровне компилятор?
      Ответить
      • Можешь пропатчить компилятор, и тогда будет на уровне компилятора
        Ответить
        • Захардкодить дефайны в конпелятор?
          Ответить
          • Почему дефайны? Можно __builtdin подобавлять всяких, только будет малость многословно. Их тогда можно в более короткие дефайны завернуть
            Ответить
            • > Почему дефайны?

              Чтобы свести задачу к уже решённой в этом треде.
              Ответить
              • Проблема только в том, что препроцессор это не компилятор.

                Хотя вот кажется в MSVC препроцессор и компилятор в один бинарь запихали. Ну а что еще можно было ждать от мелкомягких?
                Ответить
                • А как это у GCC? там препроцессор реально в ``cpp`` или это просто фронтэнд к чему-то отдельному?
                  Ответить
                  • Это отдельная программа, хоть она и входит в поставку GCC. Бинарь gcc ее не содержит внутри себя, и он ее тупо вызывает, можешь в strace проверить.

                    stat("/usr/lib/gcc/x86_64-linux-gnu/9/cc1", {st_mode=S_IFREG|0755, st_size=25654616, ...}) = 0
                    access("/usr/lib/gcc/x86_64-linux-gnu/9/cc1", X_OK) = 0
                    pipe2([3, 4], O_CLOEXEC)                = 0
                    vfork()                                 = 290407
                    close(4)                                = 0
                    read(3, "", 16)                         = 0
                    close(3)                                = 0
                    wait4(290407, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 290407
                    --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=290407, si_uid=1000, si_status=0, si_utime=4, si_stime=5} ---
                    getpid()                                = 290406
                    Ответить
                    • cc1 — это и препроцессор, и компилятор.

                      gcc и cpp просто вызывают cc1 с разными параметрами.
                      Ответить
                      • https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
                        Да, похоже что так. Там даже отдельная опция для раздельного препроцессирования-компилирования есть

                        -no-integrated-cpp

                        Perform preprocessing as a separate pass before compilation. By default, GCC performs preprocessing as an integrated part of input tokenization and parsing. If this option is provided, the appropriate language front end (cc1, cc1plus, or cc1obj for C, C++, and Objective-C, respectively) is instead invoked twice, once for preprocessing only and once for actual compilation of the preprocessed input. This option may be useful in conjunction with the -B or -wrapper options to specify an alternate preprocessor or perform additional processing of the program source between normal preprocessing and compilation.
                        Ответить
                  • У GCC всё запутано. Бинарники «gcc» и «cpp» — это всего лишь оболочки, которые запускают бинарники «cc1», «cc1plus» или «cc1obj», лежащие в /lib/gcc. Вот этот вот «cc1» и есть препроцессор и конпелятор для сишки.

                    Ну а что ещё можно было ждать от гнутых?
                    Ответить
                    • А есть еще collect2, который является частью GCC, но в отдельном бинарнике. А есть /usr/bin/as, /usr/bin/ld из бинутилсов, которые уже не являются частью GCC.
                      Ответить
                      • Точно. Я и забыл про него.

                        Вот тут всё описано:
                        https://gcc.gnu.org/onlinedocs/gccint/
                        Ответить
                • Я запускаю cpp чтобы конпелировать c++, а он какую-то хуйню выдаёт вместо бинарника.
                  Ответить
                  • .cpp файлы нифига не запускаются ``cpp``
                    .java файлы нифига не запускаются ``java``
                    .mc файлы нифига не запускаются ``mc``

                    в юниксе нет логики
                    Ответить
                • > в MSVC препроцессор и компилятор в один бинарь запихали

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

                  В MSVC имя функции это литерал. А в остальных конпеляторах это локальный массив, как и требует стандарт. В итоге в MSVC имя можно было конкатенировать с чем-то ещё, а в других конпеляторах -- нет.
                  Ответить
                  • Приведи реальный пример.
                    Ответить
                    • Ну банально __FUNCTION__ ": " для какого-нибудь лога. По стандарту так нельзя, двоеточие надо отдельно рисовать.
                      Ответить
                      • а, пнятно
                        Ответить
                      • Т. е. различается реализация макросов, вшитых в компилятор?
                        Ответить
                        • Да, по стандарту там никакой магии не должно быть. Просто в начале каждой функции есть массивчик __func__, который содержит её имя. А дальше конпелятор с линкером его выкинут, если ты им не воспользовался.

                          В MSVC же выебнулись и сделали его псевдо-макросом, который раскрывается в литерал. Что, конечно, удобнее.
                          Ответить
                          • З.Ы. Кстати, походу это всё-таки не часть препроцессора, а именно в конпелятор зашито. Вряд ли препроцессор настолько шарит в шаблонах и классах.
                            Ответить
                            • Так там компиляционная стадия и препроцессирование смешиваются, так что хуй поймешь что где

                              И это определенно добавит ебли всяким инструментам для стат. анализа, которые код после препроцессора должны хавать
                              Ответить
                              • cl /E у MS умеет показать выхлоп после процессирования

                                Интересно, что решарпер как-то умеет макросы во время стат анализа (думмется мне, ему clang помогает)
                                Ответить
                                • И там кста имена функций не раскрыты.

                                  Какая абстракция )))
                                  Ответить
                                  • ни ``cpp`` ни ``cl /E`` у меня не заменяют __FUNCTION__
                                    но оба заменяют __LINE__
                                    Ответить
                                    • > но оба заменяют __LINE__

                                      Ну тут всё по стандарту, гцц тоже заменяет лайн и файл.
                                      Ответить
                                    • > __FUNCTION__
                                      Ня нужен. Это древнее нястандартное расширение. Правильные девочки-волшебняцы использнуют "__func__" (который по Стандарту ня макрос, кстати).
                                      Ответить
                                • > cl /E у MS умеет показать выхлоп после процессирования

                                  И что он покажет с этой вот __FUNCTION__ ": " ?

                                  https://docs.microsoft.com/ru-ru/cpp/preprocessor/predefined-macros?view=msvc-160
                                  __FUNCTION__ определяется как строковый литерал, содержащий недекорированное имя включающей функции. Макрос определен только в пределах функции. Макрос __FUNCTION__ не разворачивается, если используется параметр компилятора /EP или /P . Пример использования см. в разделе для макроса __FUNCDNAME__.

                                  Про /E там ничего не сказано.

                                  Препроцессор GCC эту __FUNCTION__ ни во что не раскрывает т.к. языка Си он не знает
                                  Ответить
                  • поясни
                    #include <stdio.h>
                    
                    #define r(X) X ## uts("hello");
                    
                    void main() {
                            r(p)
                    }
                    Ответить
                    • Тут всё тупо. «uts» — это ещё не имя функции. Это произвольный текст, семантика которого ещё не ясна. Только в месте вызова r(p) макрос начнёт разворачиваться, и там «p ## uts» станет именем функции.
                      Ответить
                      • я думал, что борманд про это говорит, удивился, и привел пример того, что работает
                        Ответить
    • Лютая годнота. Очень си-нтак-си-ально.

      Ну все чудеса завязаны на typeof. По-моему уже обсуждали это и сошлись что неплохо бы завести его в стандарт.
      Ответить
      • Ещё «Царь» говорил, что «гэцэцэ» — это единственный вменяемый конпелятор.
        Ответить
        • Когда Царь крестился он вполне благосклонно говорил о clang / llvm.

          Который потом всякая анскильная шваль и своровала для своей дrustни.
          Ответить
        • Последнее из писания Царя-батюшки:

          clang/llvm
          
          Здесь наиболее показатель пример llvm. Родился как продукт мира С/С++ призванный служить скриптухе. Обделался.
          Скриптуха оказалась ни на что не способной. Был создан clang, а далее llvm стал развиваться как его часть.
          
          И всё точно так же. Существуют такие же внутренние противоречия, дяди так же обеспечивают существование скриптухи за своё счёт потому, что это позволяет им поддерживать мир С/си с классами.
          Так же через это дяди эксплуатирую других дядей. Создав такую систему, что если другим дядям нужно что-то сделать для С/С++ - они вынуждены делать, в том числе, и для остального дерьма.
          
          В данном случае меня это не особо интересует - всё это очевидно. Остановлюсь только на том, какие проблемы это производит для нас(последователей пути пацана).
          Как-то многосложно разбирать это сейчас не выйдет - необходимо описать множество базовых концепций, без понимания которых понять что-то будет почти невозможно. 
          gcc
          
          gcc архитектурно лучше, но только как компилятор. Во всём остальном всё те же проблемы, а семантических возможностей вообще нет.
          
          clang
          
          Написан как дерьмо. Это целиком и полностью дырявое, убогое дерьмо. 
          
          Если кратко, то оно содержит очень мало семантической информации. В целом оно создано только для одного - обойти его и сгенерировать ir. Обходит оно эту проблему следующим образом.
          Есть некая помойка - sema. Это тысячи всяких дырявых состояний и методов, которые произвольным образом в момент парсинга инициализируются и вызываются.
          После того, как ноды будут сгенерированы, шаблоны инстанцированы и прочее - sema просирается и вся информация тоже.
          В ast ничего не попадаёт, кроме совсем примитивной херни.
          Ответить
          • Ему не понравилось, что для добавления новых возможностей зачастую нужно патчить саму «LLVM», а патчами к «LLVM» воспользуются авторы других фронтендов, не только «C» и «C++». Так?
            Ответить
            • Проблема «LLVM» в том, что «LLVM» это всего лишь очередное middle-end говнопредставление для компилятора для ЭВМ с фон Неймановской архитектурой (и я не могу сказать, что оно лучше абстрактного представления из того же GCC), а адепты этого «LLVM» его презентуют как некую волшебную silver bullet хуйню которая все проблемы порешает в области построения компиляторов и JIT хуйни.
              Ответить
          • У царя вроде какой-то телеграм канал есть, но я этой заедушной парашей не пользуюсь.
            Ответить
            • https://t.me/proriv_zaparti2/
              https://t.me/tzar_blog
              Ответить
              • Если бы это был канал (в терминах «Телеграма»), его можно было бы посмотреть в браузере (тогда бы появилась кнопка «Превью»), а это обычный акк или бот, а их «Телеграм» в браузере не показывает...
                Ответить
              • https://t.me/proriv_zaparti2/2705

                Можно брутом номера поста посмотреть всю ленту. Странно, похоже на канал, а кнопки «Preview channel» нет.

                Кстати: «Roman». Доцента СФУ тоже зовут Романом. Это всё-таки он?
                Ответить
                • > Можно брутом номера поста посмотреть всю ленту.

                  Какая секурность )))
                  Ответить
                • У меня с одних адресов показывает пустой ебмед, а с других посыл поставить телеграф
                  Ответить
                  • 2705 у меня показывает такой текст:
                    Roman in Прорыв запарты
                    |Serg
                    |https://www.linux.org.ru/forum/development/16404998?cid=16407771 Осталась ссылка на "поехавший был пойман на базовом балабольстве «сегфолт в c++»"?
                    что-то много докшолят в последнее время меня косплеит
                    t.me/proriv_zaparti2/2705
                    Jul 10 at 20:43
                    Ответить
                    • > что-то много докшолят в последнее время меня косплеит

                      Кстати Царь-то в последнее время не настоящий.
                      Он крестился, у него изменился сленг, да и прежняя искра пропала куда-то.
                      Ответить
                    • Я понял, как этот клоакинг устроен.

                      Отдельно открытый iframe с той сраницы в зависимости от PHP_REMOTE_ADDR показывает либо текст выше, либо нагло пездит
                      Channel with username @proriv_zaparti2 not found
                      Ответить
                      • Чтобы посмотреть голый фрейм, нужно добавить параметр ?embed=1

                        И для разных айпишников он отдаёт разный конь-тент?
                        Ответить
                • >Странно, похоже на канал, а кнопки «Preview channel» нет

                  Не. Это похоже группа (кнопка View In Group ), и посты от разных авторов.
                  Ответить
                  • Да, теперь понял. Просто я не знаком с «Телегой».

                    Почему они так некокококонсистентно сделали: каналы показывают в браузере целиком, а из группы только отдельные посты?
                    Ответить
                    • Олимпиадники, сер.
                      Ответить
                    • Для групп это видимо сделано чтобы с одной стороны можно было что-то оттуда процитировать, сославшись на хуйню обычной ссылкой, а с другой стороны - ну надо же как-то мотивировать ставить пашкограм, и поэтому только через говнограм есть функция, чтобы удобно всё пордяд смотреть. А то вот будут всякие там халявщики просматривать группы просто так, разве это можно допускать?
                      Ответить
                  • > (кнопка View In Group )
                    Вот это тоже есть если смотреть с адреса, который в уголке дурова не помечен как «арбузный»
                    Ответить

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