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

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    // Там в стандарт сишки хотят добавить хуйни какой-то
    
    // https://habr.com/ru/company/badoo/blog/503140/
    // C2x: будущий стандарт C
    
    // Итак, с опозданием лет на 20 к нам приходят функции strdup и strndup!
    #include <string.h>
    
    char *strdup (const char *s);
    char *strndup (const char *s, size_t size);

    Они есть в позикс стандарте, да и вообще эти функции - говно, как и нуль-терминированные строки сами по себе.

    Запостил: j123123, 23 Мая 2020

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

    • > У разработчиков больших компиляторов C есть любимая игра: придумывать собственные расширения к языку в форме атрибутов объявлений и определений. Сам язык, конечно же, специального синтаксиса для таких вещей не предоставляет, поэтому каждый изощряется как может.

      > Чтобы хоть как-то привести этот балаган к порядку без создания десятков новых ключевых слов, комитет придумал синтаксис-который-будет-управлять-всем. Словом, в следующей версии стандарта принимается синтаксис для указания атрибутов. Пример из предложения:


      [[attr1]] struct [[attr2]] S { } [[attr3]] s1 [[attr4]], s2 [[attr5]];


      > Здесь attr1 относится к s1 и s2, attr2 относится к определению struct S, attr3 — к типу struct s1, attr4 — к идентификатору s1, attr5 — к идентификатору s2.

      Лучше бы приняли за стандарт хуйню из GCC для атрибутов. Впрочем, похуй.

      > Устаревший ещё в 1989 году такой способ объявления параметров функции, как «объявление в стиле K&R» (он же — «когда типы после скобочек указываются», он же — «я не понимаю старый код на C»), будет, наконец, сожжён на костре, а я смогу расслабиться и не следить за своими void-ами.

      > Другими словами, больше нельзя будет делать так:


      long maxl (a, b)
          long a, b;
      {
          return a > b ? a: b;
      }


      Так уже никто не делает. Такую хуйню можно встретить только во всяком древнем говне, которое при этом обычно переписывается при попадании на глаза.
      Ответить
      • >Эпоха Просвещения приходит в код на C! Объявления функций будут делать именно то, что приличные люди от них ожидают:

        /* объявление функции без аргументов */
        int no_args();
        
        /* тоже объявление функции без аргументов */
        int no_args(void);


        Похуй вообще.

        > Представление знаковых целых чисел

        > Бесконечная, казалось бы, история близка к завершению. Комитет смирился с тем, что единорогов и сказочных архитектур не существует, а программисты на C имеют дело с дополнительным кодом (англ. two's complement) для представления знаковых целых чисел.

        > В текущем виде это уточнение немного упростит стандарт, но в перспективе поможет (!) избавиться от «любимого» программистами неопределённого поведения языка — переполнения знакового целого числа.


        Похуй вообще №2.

        >Реализация одного из положительно оценённых комитетом предложений позволит не указывать лишний раз имена параметров в определениях функций:

        int main(int, char *[])
        {
        /* И никакой перхоти! */
        return 0;
        }

        > Мелочь, но какая приятная!

        Похуй вообще №3.

        > После долгого, до-о-олгого переходного периода комитет, наконец, решил больше не придуриваться и принять в язык, эм, «новые» ключевые слова: true, false, alignas, alignof, bool, static_assert и другие. Заголовки вроде <stdbool.h> можно будет, наконец, почистить.

        Норм. Хотя тоже примерно похуй
        Ответить
        • > Кажется, на смену проблемному макросу NULL приходит ключевое слово nullptr, которое будет эквивалентно выражению ((void*)0) и при приведении типов должно оставаться типом-указателем. Любое использование NULL предлагается сопровождать предупреждением компилятора:

          /* Вы же никогда не пишете просто NULL? Я вот до сих пор затылок чешу. */
          int execl(path, arg1, arg2, (char  *) NULL);
          
          /* Но счастье близко */
          int execl(path, arg1, arg2, nullptr);


          Тоже мне. #define REALLYNULLPTR ((void*)0)
          Ответить

          • > Реформа обработки ошибок в стандартной библиотеке

            >Обработка ошибок функций стандартной библиотеки — давняя проблема C. Сочетание неудачных решений в ранних версиях стандарта, консервативности комитета и вопросов обратной совместимости не позволяло найти устраивающее всех решение.

            >И вот наконец нашёлся герой, готовый предложить решение одновременно разработчикам компиляторов, сверхконсервативному комитету и нам, простым смертным:


            [[ oob_return_errno ]] int myabs (int x) {
                if(x == INT_MIN ) {
                    oob_return_errno ( ERANGE , INT_MIN ) ;
                }
                return (x < 0) ? -x : x;
            }


            > Обратите внимание на атрибут oob_return_errno. Он означает, что из этой функции-шаблона будут сгенерированы следующие функции:

            > 1. Возвращающая структуру с флагом ошибки и результатом работы функции (struct {T return_value; int exception_code}).
            > 2. Возвращающая результат работы функции и игнорирующая возможные ошибки в аргументах, приводя к неопределённому поведению.
            > 3. Завершающая выполнение в случае ошибки в аргументах.
            > 4. Заменяющая errno, то есть обладающая привычным поведением.


            Слишком сложно. Хуйня какая-то.
            Ответить
            • > Оператор typeof

              > Ключевое слово typeof уже давно реализовано в компиляторах и позволяет не повторяться при написании кода. Канонический пример:


              #define max(a,b)                                \
                  ({ typeof (a) _a = (a);                     \
                  typeof (b) _b = (b);                        \
                  _a > _b ? _a : _b; })



              > Мартин Себор (Martin Sebor), ведущий разработчик из Red Hat и участник Комитета, утверждает, что соответствующее предложение уже находится в работе и почти наверняка будет одобрено.

              Тут не только typeof но еще и хуйня https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html так что надо не забыть еще и эту хрень в стандарт затащить.
              Ответить
              • > Оператор defer

                > Некоторые языки программирования, в том числе и реализованные на базе Clang и GCC, позволяют привязывать высвобождение ресурсов к лексическим областям видимости переменных или, проще говоря, вызывать какой-то код с выходом программы из области видимости переменной.

                > В чистом C нет и никогда не было такой возможности, но компиляторы уже давно реализуют атрибут cleanup(<cleanup function>):


                int main(void)
                {
                    __attribute__((cleanup(free))) char *s = malloc(sizeof(*s));
                    return 0;}



                > Роберт Сикорд (англ. Robert Seacord), автор «Effective C» и член комитета, признался, что работает над предложением в стиле ключевого слова defer из Go:

                int do_something(void) {
                    FILE *file1, *file2;
                    object_t *obj;
                    file1 = fopen("a_file", "w");
                    if (file1 == NULL) {
                      return -1;
                    }
                    defer(fclose, file1);
                
                    file2 = fopen("another_file", "w");
                    if (file2 == NULL) {
                      return -1;
                    }
                    defer(fclose, file2);
                
                    /* ... */
                
                    return 0;
                  }


                > В приведённом примере функция fclose будет вызвана с аргументами file1 и file2 при любом выходе из тела функции do_something.

                Зачем тащить хрень из какого-то Goвна, если есть GNU расширения? Чтоб легче сишникам переходить на Go и Go-шникам на Си?

                > Близится революция!

                Хуеволюция
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                • Про этот __attribute__((cleanup(free))) у меня кстати есть отдельный говнокод
                  Смотрите какая хуйня: https://govnokod.ru/25526#comment471379 - там кстати и typeof есть.
                  Ответить
                  • Defer вообще из Ди украли. Там он называется scope(exit)
                    Ответить
                  • Так нельзя зделать?
                    file1 = dfopen("a_file", "w"); //    auto defer(fclose, file1);
                        if (file1 == NULL) {
                          return -1;
                        }
                    Но это уже попахивает деструкторами, да.
                    Ответить
                • >позволяют привязывать высвобождение ресурсов к лексическим областям видимости переменных или, проще говоря, вызывать какой-то код с выходом программы из области видимости переменной.

                  Зайчатки RAII в сишке.
                  Ну может какая-то польза и будет. Остальное хуйня нинужная.
                  Да и это goвнище.
                  Должен быть autodefer на fopene.
                  Ответить
            • Ультракостыли
              Ответить
            • > 1. Возвращающая структуру с флагом ошибки и результатом работы функции (struct {T return_value; int exception_code}).

              Что мешает сделать такой struct сейчас, не меняя язык?
              Ответить
              • показать все, что скрытоvanished
                Ответить
                • Ну возможно придётся сделать *новые* функции, но это лучше чем менять язык.
                  Я вообще не понимаю что c abs не так.
                  Что так нужен if, что со структом он нужен. Что так питушня, что эдак.

                  Но если они планируют завезти новые функции, то пусть сделают struct.

                  >Алсо, к такой структуре хорошо бы завести маттерн патчинг
                  Да. Лучше бы свищ свой дырявый починили, и сделали по-нормальному.
                  Паттерн-матчинг в Сишке — это слишком круто чтобы быть правдой.
                  Ответить
        • > Похуй вообще.
          > Похуй вообще №2.
          Язык очищают от говна и питушни в поведении по умолчанию. Это же круто, как можно так реагировать? Наконец, можно нормально использовать числа!

          Кстати, что там с union и кастами pituz* -> void* -> other_pituz*? Их хоть починили?
          Ответить
          • Касты через union в Си давно починили, а в крестоговне это вроде как так и осталось неразрешенным https://govnokod.ru/25353#comment457026
            Ответить
          • > и кастами pituz* -> void* -> other_pituz*

            А что ты там предлагаешь чинить?
            Ответить
            • Если там нельзя положить одну питушню, а достать другую без подвохов, то это надо чинить. Скажем, чтобы можно было взять любую пару типов char[4], int32_t и float и читать-писать их. И чтоб без UB, внезапных паддингов, выравниваний и *конечников.
              Ответить
              • Есть __attribute__ (( aligned (1) )) и __attribute__((__may_alias__)) - осталось только застандартизировать для этой [[хуйни]] что в https://govnokod.ru/26687#comment549264 .
                Ответить
          • >Язык очищают от говна и питушни в поведении.

            Про ECMAScript тоже так говорили.
            Итог будет примерно такой же.
            Ответить
        • >int main(int, char *[])
          > Мелочь, но какая приятная!

          Нахуя???
          Ответить
      • https://github.com/jsoftware/jsource/blob/48529033a8de07eaed6ebe6cec6e4dc762528933/jsrc/fnmatch.c#L66
        Ответить
    • > Включение двоичных файлов в исходный файл

      > Включение двоичных данных из файлов в исполняемый файл — невероятно полезная для всех игроделов возможность :


      const int music[] = {
         #embed int "music.wav"
      };


      > Надеюсь, члены комитета понимают, что Хабрасообществу известно место проведения следующего заседания, и эта директива препроцессора будет принята без вопросов.

      Игроделов на сишке? Кто на сишке сейчас всерьез делает игры? И почему ресурсы не хранить отдельными файлами? Это скорее нужно чтоб всякую хрень в прошивку впиндюривать удобней было.

      В крестах свой std::embed уже https://govnokod.ru/26022 придумали, а тут будет эмбед через препроцессор работать, или все ж на уровне компилятора?

      Да и не очень-то сильно нужна такая хуйня, можно объектные файлы из произвольных бинарников генерить https://balau82.wordpress.com/2012/02/19/linking-a-binary-blob-with-gcc/

      А еще бинарные блобы в крестоговнео можно через какие-нибудь constexpr-функции прогнать, а у сишки с этим есть ограничения.
      Ответить
      • Тоже давно есть в Ди. В компайлтайме файлик можно прочесть и кода нагенерить. Напрмер, protobuf или IDL какой можно модулем сделать, а не отдельной тулзой генерить.
        Ответить
      • Круто.
        void pituh()
        {
            static const char data[] = {
                #embed char "low-level-pituh.obj"
            };
            typedef void proc();
            ((proc*)data)();
        }
        Ответить
        • const char shellcode[] __attribute__ ((section ("text"))) =
            "\x48\x31\xf6\x56\x48\xbf"
            "\x2f\x62\x69\x6e\x2f"
            "\x2f\x73\x68\x57\x54"
            "\x5f\xb0\x3b\x99\x0f\x05";
          
          
          int main(void)
          {
            (*(void  (*)()) shellcode)();
          }
          Ответить
          • показать все, что скрытоvanished
            Ответить
            • А погуглить строки лень? Или ДИЗАССЕМБЛИРОВАТЬ? Это Linux/x86_64 - execve(/bin/sh) Shellcode (22 bytes)

              Можно и шеллкод с rm -rf сделать. Только это не шеллкод будет, а rm-rfкод
              Ответить
          • Зачем это здесь?
            Ответить
            • Зачем __attribute__ ((section ("text"))) ? Чтоб байтики в исполняемом сегменте были, а не хуй знает где.
              Ответить
              • Это от платформы и конпелятора зависит.

                Я имею ввиду зачем ты это запостил?
                Ответить
                • Я это запостил к тому, что хуйня из https://govnokod.ru/26687#comment549301
                  void pituh()
                  {
                      static const char data[] = {
                          #embed char "low-level-pituh.obj"
                      };
                      typedef void proc();
                      ((proc*)data)();
                  }


                  Может не сработать, т.к. хуй его знает, в какую секцию компилятор хуйнет этот data. Нужно еще секцию указывать
                  Ответить
                  • А, так это от платформы и конпелятора зависит.
                    Ответить
                    • Подтверждаю.

                      http://govnokod.ru/25359#comment458045
                      Ответить
                    • Может быть это стандартизируют, и будет один конкретный способ указывать, в какую секцию какую хуйню пихать.
                      Ответить
                      • На уровне языка можно стандартизировать синтаксис прагм. На уровне платформ стандартизировать названия секций не получится. В «Windows» и в «UEFI» используется формат «PE», в «Линуксе» — «ELF», в «Mac OS X» — «Mach-O»...

                        • Форматы «ELF» и «PE» позволяют к экзешнику добавлять секции с произвольными именами и с произвольными атрибутами (чтение, запись, исполнимость).

                        • «Mach-O» позволяет добавлять секции, но с набором атрибутов из шаблона («для кода», «для данных»), да и на название секции там какие-то ограничения. Вроде нужно выбирать название из готовых.

                        • «a.out» вообще не позволяет добавлять секции, в нём три готовые секции, даже секции для констант нет.

                        Если «ELF» и «PE» вытеснят остальные форматы, тогда можно будет говорить о стандартизации. А пока всё равно будет куча платформозависимого кода, ифдефы — вот это всё.
                        Ответить
                        • a.out не нужен
                          Ответить
                        • в COM нет никаких секций
                          И именно по этому я за
                          Ответить
                          • Да, и вся память доступна для записи и для исполнения, даже память чужих процессов и самой операционки.
                            Ответить
                            • Даже небо, даже аллах.

                              На самом деле не Всегда вся. В v86 может быть Злой Гипервизор:)
                              Ответить
                              • Гуляла за городом Божья коровка,
                                По веткам травинок карабкалась ловко,
                                Глядела, как в небе плывут облака…
                                И вдруг опустилась Большая Рука.
                                И мирно гулявшую Божью коровку
                                Засунула в спичечную коробку.
                                Коровка ужасно сердилась сначала,
                                Мычала и в стены коробки стучала…
                                Но тщетно! Забыли о ней в коробке,
                                Закрыли Коровку в шкафу, в пиджаке.
                                Ах, как тосковала в коробке бедняжка!
                                Ей снились лужайка, и клевер, и кашка…
                                Неужто в неволе остаться навек?!
                                Коровка решила готовить побег.

                                Три дня и три ночи рвалась она к цели.
                                И вот, наконец, вылезает из щели…
                                Но где же деревья, цветы, облака?
                                Коровка попала в карман пиджака.
                                Однако она, не теряя надежды,
                                Бежит на свободу из душной одежды:
                                Там солнце, и ветер, и запахи трав…
                                Но вместо свободы увидела шкаф!
                                Тоскливо и страшно Божьей коровке.
                                Опять она в тёмной пустынной коробке.
                                Вдруг видит: вверху, где вставляется ключ,
                                Сквозь щёлочку в шкаф пробивается луч!
                                Скорее на волю! Коровка отважно,
                                Зажмурясь, штурмует замочную скважину…
                                И вновь оказалась в глухом коробке
                                С огромною люстрой на потолке.
                                Однако Коровка на редкость упряма:
                                Нашла, где неплотно захлопнута рама…
                                И вот вылезает она из окна —
                                Ура! Наконец на свободе она!

                                И вновь на знакомой лужайке букашка.
                                Под нею, как прежде, колышется кашка,
                                Над нею плывут в вышине облака…
                                Но смотрит на мир осторожно Коровка:
                                А вдруг это тоже Большая коробка,
                                Где солнце и небо внутри коробка?!
                                Ответить
                                • Да, Усачев неплохо описал устройство виртуализации
                                  Ответить
      • > И почему ресурсы не хранить отдельными файлами?
        Ну положим засирать диск пользователя тыщей файлов -- не комильфо.
        Но в PE есть же секции для говна (ака виндовые ресурсы), нет разве?

        Я там когда-то банку сгущиконку хранил
        Ответить
    • Не понимаю нахрюка, в отличие от крестостандартизаторов сишкостандартизаторы понемногу добавляют в язык удобные штуки, а не функции Бесселя.
      Ответить
      • Да, в отличии от крестов тут всё более-менее нормально, только с [[ oob_return_errno ]] хуйня какая-то. Сишка более рационально развивается, а не обрастает тоннами хуйни
        Ответить
        • По-моему Сишка обрастает тоннами хуйни. Только недокрестовой.

          > [[ oob_return_errno ]]
          Яиц взять крестоисключения не хватило. Ума сделать просто struct тоже.

          >defer(fclose, file2);
          Недодеструкторы. Зачем? Зачем?

          Экономии никакой, даже больше кода чем просто в конце вызвать fclose(file2).
          Ответить
          • показать все, что скрытоvanished
            Ответить
            • Ручной defer нинужен. Ничего полезного он не добавляет и его можно забыть позвать. С тем же успехом я могу написать goto в конец функции и там всё позакрывать.
              Ответить
              • показать все, что скрытоvanished
                Ответить
                • > int petuh очистится

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

                      А для закрытия файла или освобождения кучи надо что-то позвать. А что именно надо позвать? А хуй знает, никто компилятору это не объяснил. А надо ли звать вообще? Вдруг я хочу оставить файл открытым? И это тоже конпелятору никто не объяснил.
                      Ответить
                      • показать все, что скрытоvanished
                        Ответить
                        • Скорее в сложности языка. Сейчас control flow у сишки максимально тупое и понятное (если отбросить longjmp). Для управления ресурсами же понадобится куча новых конструкций и инфы.

                          Видимо поэтому и добавили ручной defer на отъебись.
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                            • > а зачем

                              Да хер знает. Видимо любители портянок их уломали чтобы defer(close) писать рядом с open'ом, а не через 10 экранов...
                              Ответить
                              • показать все, что скрытоvanished
                                Ответить
                                • Я думаю lifo всё-таки.
                                  Ответить
                                  • показать все, что скрытоvanished
                                    Ответить
                                    • Ну Шляпа пролезла в комитет, и давай умничать: defer, oob_return_errno, kokoko.

                                      Надо бы пару вызовов systemd в сишный стандарт прописать.

                                      Это как мем «в конституцию внесут пункт о том что...»

                                      >сложная сишечка не нужна
                                      С11 Enterprise. Поттерингам неудобно писать говна без deferов.
                                      Ответить
                                      • О, так тогда проблем с пулом нет.
                                        defer по dbus посылает хендлы в systemd-poold, и там они хранятся.
                                        Ответить
                              • > Видимо любители портянок их уломали чтобы defer(close) писать рядом с open'ом, а не через 10 экранов...

                                Скорее любители макросов.
                                Я могу сделать #define OPEN_FILE()
                                И немного упростить себе жизнь.
                                Но зачем? Если можно autodefer в функцию открытия вынести и не петушиться.
                                Ответить
                                • > autodefer

                                  А как? Это ж по сути новое соглашение о вызове получается. Ну либо дополнительная инфа в прототипе. Плюс нужен какой-то способ отменить автодефёр если я хочу этот файл куда-нибудь прикопать или вернуть...
                                  Ответить
                                  • Ну сделать новые функции. Типа dfopen. Или новый режим fopen("file","w+autoclose")

                                    Кстати я не понимаю как будет работать сам defer, пусть даже явный.

                                    Это же внутри функции будет небольшой деструктор. Что для Сишки как-то нетипично.
                                    Ответить
                                    • Кстати, а я же могу defer в цикле звать и наоткрывать тыщу файлов? Где они это вообще хранить собрались? В каком-то пуле, из которого создаётся список откатов?
                                      Ответить
                                      • Да. В goвне можно в цикле.

                                        >Кстати, а я же могу defer в цикле звать и наоткрывать тыщу файлов?
                                        https://tour.golang.org/flowcontrol/13
                                        fmt.Println("counting")
                                        
                                        	for i := 0; i < 10; i++ {
                                        		defer fmt.Println(i)
                                        	}
                                        
                                        	fmt.Println("done")
                                        }
                                        
                                        counting
                                        done
                                        9
                                        8
                                        7
                                        6
                                        5
                                        4
                                        3
                                        2
                                        1
                                        0


                                        Оно в какой-то внутренний стек ложится и срабатывает аки finally.
                                        Просто если они делают магическую питушню, пусть тогда пилят autodefer.
                                        Ответить
                                      • показать все, что скрытоvanished
                                        Ответить
                                        • Да и на симбиане такой пул был, хоть там формально и кресты.
                                          Ответить
                                        • Блять. Я уже начинаю уважать СиПлюсТрупа с его RAII, классами и деструкторами.
                                          Не думал что скажу, но в крестах они хотя бы сделали логично
                                          Ответить
                                        • Это разве defer? Это сахарок для того, чтобы релизить счётчики охулиону объектов.

                                          А обычный defer есть в Свифте. Там при попытке присобачить его внутри цикла появлется ворнинг:

                                          'defer' statement before end of scope always executes immediately; replace with 'do' statement to silence this warning
                                          Ответить
                          • > поэтому и добавили ручной defer на отъебись.

                            Так же как «исключения» на [[ oob_return_errno ]] struct {T return_value; int exception_code}

                            И «шаблоны» на препроцессоре.
                            Ответить
                            • > errno

                              Т.е. там только инт можно приклеить как out-of-band данные?
                              Ответить
                              • Я хз. Кстати что за T return_value — в Сишке же нет никакого Т!!!

                                Латентные крестухи спалились.
                                Ответить
                              • Им придётся из goвна воровать тогда всё сразу.
                                В т.ч. возврат нескольких переменных.

                                f, err := fopen("koko")
                                if (err){
                                }

                                Иначе питущня.
                                Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                                  • Разве нельзя так написать не внося изменения в язык?
                                    Ответить
                                    • показать все, что скрытоvanished
                                      Ответить
                                      • Хуиту какую-то городят стандартизаторы.

                                        На одно полезное изменение (typeof), 3 ни о чём, 3 вредных, и 3 безумных.
                                        Ответить
                                      • показать все, что скрытоvanished
                                        Ответить
                                        • показать все, что скрытоvanished
                                          Ответить
                                          • Вроде как в сишке принято самому выделять память под структурку, забивать ее нулями, а потом давать указатель на нее в функцию инитиализации.
                                            Ответить
                                          • Ну обычно у объектов есть дефолтный конструктор, поэтому просто присваиваешь поверх старого:
                                            void foo(Bar& out) {
                                                Bar local(42);
                                                out = std::move(local);
                                            }
                                            
                                            Bar b;
                                            foo(b);
                                            Если дефолтного нету - ну через указатель:
                                            void foo(std::shared_ptr<Bar>& out) {
                                                out = std::make_shared<Bar>(42);
                                            }
                                            Можещё через std::aligned_storage и placement new извратиться, но никто так не пишет.
                                            Ответить
                                            • показать все, что скрытоvanished
                                              Ответить
                                              • Дык дефолтный коньструктор обычно ничего особенного и не делает, это как инициализация нулями в сишке.
                                                Можно, конечно, как Борманд предложил — с «placement new», но это так-то багор: как минимум, тебе потом придётся руками вызывать деструктор.
                                                Ответить
                                                • guest8 видимо о том, что конструктор копирования для передачи параметров через out был неизбежен до с++11. А для сложных объектов это действительно жопа. Многие из них в принципе не копируются.
                                                  Ответить
                                                • показать все, что скрытоvanished
                                                  Ответить
                                                  • Дефолтный конструктор в 99% случаев нихуя не делает. Поэтому можешь смело создавать на стеке, передавать по ссылке и просить заполнить.
                                                    Ответить
                                                  • …А если дефолтного конструктора нет (или он есть, но открывает соединение с «MySQL» и считает последнюю цифру числа «Пи»), уко-ко-ко-затели использовать не хочется (лучше, кстати, по-умолчанию использовать unique_ptr — тогда у пользователей, которым shared_ptr не нужен, не будет лишних расходов, а кому нужен — те просто сделают «shared = std::shared_ptr(unique);»), то просто развращай std::pair/std::tuple и не нагружай моск.
                                                    Ответить
                                                    • показать все, что скрытоvanished
                                                      Ответить
                                                      • Сработает. Если не хочешь пердолиться — пару можно сконьструировать при возврате, тогда оверхед будет в один перемещающий коньструктор и один деструктор: https://wandbox.org/permlink/I1IMj1yQQnrsM9ON. Если надо м-м-максимум пирфоманса — сразу коньструируй пару, тогда получится зирокост: https://wandbox.org/permlink/ow5nRVLO7wBD46hO.
                                                        Ответить
                                                        • показать все, что скрытоvanished
                                                          Ответить
                                                          • Это всё из-за жизненного цикла объектов в крестах: объект может быть либо инициализированным, либо не существовать вовсе.
                                                            Конечно, можно было бы «для простоты» ввести неинициализированное состояние объекта, но если копнуть поглубже — такие багрища вылезут, что копирование-перемещение покажется простым и понятным механизмом.
                                                            Ответить
                                                            • показать все, что скрытоvanished
                                                              Ответить
                                                              • Думаю, самым сложным будет автоматический вызов деструктора. Так-то расклеить инициализацию и коньструирование можно и сейчас:
                                                                char *mem = new char[N];  // N.B.: не забыть поебаться с выравниванием, в такой
                                                                    // форме это, скорее всего, UB, я хз
                                                                // ...
                                                                Petuh *petuh = new (mem) Petuh();

                                                                Только вызывать деструктор, как я выше писал, придётся руками, потому что компилятор в общем случае не сможет доказать, что петуха мы инициализировали:
                                                                Petuh std:alloc_mem(petuz);
                                                                if (P == NP) {
                                                                    InitializePetuh(petuz);
                                                                }
                                                                // Деструктор вызывать только если доказали P == NP
                                                                Ответить
                                                                • В твоем примере куча задейстована, а при таком условии же можно было решить умным поинтером, не?

                                                                  Я имел ввиду ситуацию, когда я
                                                                  * выделил место на стеке
                                                                  * попросил кого-то другого заполнить его объектом.
                                                                  Ответить
                                                                  • Ну тогда придётся доказывать, что во всём графе исполнения переменную проинициализировали до ее использования. Тебе придётся доказывать, не конпелятору. Потому что конпелятор скажет "твой код слишком сложный, перепиши его", как это сейчас делает джава в подобной ситуации с конструктором.

                                                                    Поэтому крестовый вариант с "лишним" дефолтным конструктором не так уж и плох. А в очевидных кейсах компилятор его выбросит.
                                                                    Ответить
                                                                    • Да, это будет адок, кшно.

                                                                      В джаве кстати тоже модно случайно светануть неинициализированной переменной, если случится leak of this.

                                                                      public class Spam {
                                                                      
                                                                          private final int i;
                                                                      
                                                                          public Spam() {
                                                                              doAll(this); //угадай, чему там равно spam.i
                                                                              i = 42;
                                                                          }
                                                                      Ответить
                                                                      • А в Свифте так не выйдет.
                                                                        Ответить
                                                                        • А что будет, кстати?

                                                                          Кстати, а в ObjC можно было сделать alloc, а потом передать объект дальше, чтобы ему сделали init в другом месте?
                                                                          Ответить
                                                                          • Ничего не будет. Не скомпилируется.

                                                                            public class Spam {
                                                                                private var i: Int
                                                                            
                                                                                public init() {
                                                                                    doAll(spam: self)
                                                                                    i = 42
                                                                                }
                                                                            }
                                                                            
                                                                            func doAll(spam: Spam) { }


                                                                            'self' used in method call 'doAll' before all stored properties are initialized

                                                                            В Objc init это обычный метод, там не было отдельных конструкторов, можешь его назвать, как угодно и вызвать, где угодно.
                                                                            Ответить
                                                                            • Свифт молодец тогда.

                                                                              Выходит, что в ObjC выделение памяти и заполнение её данными разделено by design, понятно
                                                                              Ответить
                                                                              • Свифт молодец, но, к сожалению, его легко наебать при помощи force unwrap.

                                                                                Что касается обж си, то надо конечно сделать уточнение, что init это метод NSObject, потому он так или иначе есть в (практически?) любом классе на обж си.

                                                                                Ещё есть new: Allocates a new instance of the receiving class, sends it an init message, and returns the initialized object.
                                                                                Ответить
                                                                            • показать все, что скрытоvanished
                                                                              Ответить
                                                                  • Неважно, placement new работает с любой памятью.
                                                                    // N.B.: memForPetuh выделен на стеке
                                                                    typename std::aligned_storage<sizeof(Petuh), alignof(Petuh)>::type memForPetuh;
                                                                    // N.B.: куча не задействована, это просто инициализация объекта Petuh
                                                                    // по адресу memForPetuh
                                                                    Petuh *petuh = new(&memForPetuh) Petuh();
                                                                    Ответить
                                                                    • ахаха, работает
                                                                      #include <iostream>
                                                                      
                                                                      class Petuh
                                                                      {
                                                                      public:
                                                                      	int iq = 0;
                                                                      
                                                                      	Petuh(int i)
                                                                      	{
                                                                      		std::cout << "Initialized with " << i << std::endl;
                                                                      		iq = i;
                                                                      	}
                                                                      
                                                                      	~Petuh()
                                                                      	{
                                                                      		std::cout << "Me goes to the soup:( " << std::endl;
                                                                      	}
                                                                      };
                                                                      
                                                                      
                                                                      void InitPetuh(std::aligned_storage<sizeof(Petuh), alignof(Petuh)>::type* memForPetuh)
                                                                      {
                                                                      	new(memForPetuh)Petuh(42);
                                                                      }
                                                                      
                                                                      
                                                                      int main()
                                                                      {
                                                                      	std::aligned_storage<sizeof(Petuh), alignof(Petuh)>::type kuratnik;
                                                                      	InitPetuh(&kuratnik);
                                                                      	Petuh* petuh = reinterpret_cast<Petuh*>(&kuratnik);
                                                                      
                                                                      	std::cout << "Coco " << petuh->iq << std::endl;
                                                                      	petuh->~Petuh();
                                                                      }
                                                                      .

                                                                      Ну по сути я отказался от любой автоматической хуйни, и сам себе злобный буратин.

                                                                      Забавные эти ваши плюсы, чего там только нету

                                                                      лучше тока было сразу кастануть, и в инициализтора принимать уже указатель на петуха
                                                                      тае понятнее
                                                                      Ответить
                                                                      • показать все, что скрытоvanished
                                                                        Ответить
                                                                        • > а бывает displacement delete, лол?
                                                                          Не, не завезли. Только ручками сначала звать деструктор, а потом удалять память (по указателю того типа, который изначально создавался через new).
                                                                          Ответить
                                                                          • В моём случае не надо ничо удалять, потому что этот ваш aligned_storage у меня на стеке же. Достаточно вызвать деструктор
                                                                            Ответить
                                                                            • Да, именно. А delete в крестах — это всё же про освобождение выделенной в куче памяти.
                                                                              Ответить
                                                                              • показать все, что скрытоvanished
                                                                                Ответить
                                                                                • Можно std::align() заюзать, чтобы точно не багриться с баграми про кратность.

                                                                                  > Кстати, alignof разве не должен совпадать с sizeof на x86?
                                                                                  Дык в «x86» нет никаких «struct»/«class», там только байты/слова/двойные слова/четверные слова.
                                                                                  Ответить
                                                                                  • показать все, что скрытоvanished
                                                                                    Ответить
                                                                                    • > Или я путаю?
                                                                                      Не знаю, я не настолько глубоко погружался в x86. Но в общем-то звучит логично.
                                                                                      Впрочем, конкретно с крестами это не работает: в них выравнивание по Стандарту может быть только степенью двойки (включая нулевую степень — для char).
                                                                                      Ответить
                                                                                    • А если у массива элемент размером 5 байт, то его нужно класть по адресу, кратному 5? Звучит логично с точки зрения конпелятора (тогда адреса элементов легко считать), но бесполезно с точки зрения процессора: у процессора нет инструкции «прочитать 5-байтовое число», а есть инструкции для чтения байта, ворда, дворда, куворда. И именно инструкция чтения какого-нибудь дворда может обломаться и физически превратиться в две операции чтения, если адрес не выровнен на дворд, получим штрафные такты.
                                                                                      Ответить
              • А я о чём.
                Только кода больше.
                >defer(fclose, file2);
                >fclose(file2);
                Ответить
    • показать все, что скрытоvanished
      Ответить
    • Ну раз нуль терминированные строки говно - паскаль-строк этому господину. Хотя можно подизьебнутся с псевдоклассом - но то срачей будет в комитете стандартов.

      А пространств имен в и операторов типа new/delete в си так и не добавили, что жаль.
      Ответить
      • Пусть тебя не тяготит эта оказия. Будучи великомученником (а мучать я тебя буду страшно), ты попадешь прямо в рай.
        Ответить
    • >habr.com/ru/company/badoo/blog
      >>habr.com/ru
      >>company/badoo
      Да сишка фуфло.
      В стандарт никак не завезут функции, чтобы поставить like какой-то нибудь инстаграмной курице.
      Ответить
      • показать все, что скрытоvanished
        Ответить
        • Зато в позиксе она есть. Одна на процесс, без ресайза и удаления элементов.
          Ответить
        • В Сишке мапы и сеты встроены прямо в язык. Называются «массив».
          Царь показывал:
          uint8_t set[255]={
          [A]=1
          ,[В]=1
          ,[C]=1
          };
          Ответить
          • Поиск за O(1) — одной инструкцией процессора (косвенная адресация).
            Ответить
            • Как и в структуре, угу

              Сплошной O(1). Супероптимальный язык
              Ответить
          • Офтопик. Упоротая сортировка массивов на оценку:
            https://govnokod.ru/24496
            Ответить
        • Какой пердолинг )))

          Если почитать интернеты, хороший программист - это пердоля, который знает все кишки процессора, знает все реализованные в библиотеках алгоритмы, не признаёт скриптушню, динамическую питуизацию, ГЦ и другие удобства.

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

            И правильно делает.

            >Но это не со зла, это из-за банальной зависти.

            Конечно не со зла. С жалости.

            >Пока скриптушок дописывает десятую программу
            https://www.npmjs.com/package/is-eq-ten

            Сишники пишут libfoo, которую интегрируют в сотни проектов.
            Ответить
          • vanished
            Ответить
            • Можно смело закрывать этот бизнес, начинать следующий. Со следующим-то точно повезёт!
              Ответить
              • Нужна фирма, оказывающая пирдолинговые услуги.
                Вызываешь пирдолинг-инженера, и он решает все проблемы.

                Отличная идея для стартапа, кстати
                Ответить
            • > Антипирдоля денег конторы не тратит. А потом у него не устанавливается модуль питона или не создается COM объект, и на этом работа конторы заканчивается.
              Модули питона должен устанавливать админ. Уметь состыковывать имеющиеся разношёрстные модули и создавать свой код - это разная работа разных людей.
              Ответить
              • > разных людей

                Именно после таких вот принцесс, которым лишь бы код нахуярить, а как это в проде запускаться будет пусть админ пердолится, и появилась культура девочек-собачек.
                Ответить
                • а разве девочки собачки это не про то, чтобы настраивать окружения не вучную, а через конфигурейшен-аз-кодерствм?
                  Ответить
                  • Отчасти. На практике это про "Чего балерине^W программисту зря крутиться? Ей бы к ноге динамо-машину^W^W админство присобачить".
                    Ответить
              • Неспортивно цитировать воннишд, пользуясь платным аккаунтом
                Ответить
    • Единственное полезное из всего: typeof.
      Ответить
      • Почему вы так любите английские слова? Ехали бы в англию!
        Ответить
    • 3.2. WG21 P0709 Deterministic C++ Exceptions 
      As this is a WG14 focused paper, this section will be extremely brief, but it is worthdemonstrating howCcode could safely and usefully call many more C++ functions in thefuture than at present.
      Assuming that [WG21P1028] SG14 status_code and standard error object for P0709
       Zero-overhead deterministic exceptions becomes the chosen std::error for lightweight exceptions, implementing C support for calling C++ functions which throw lightweight excep-tions is straightforward. 
      
      Under the [WG21 P1095] formulation of P0709, deterministic exception throwing functionscan locally throw a to-std::error convertible custom type more appropriate to a local usecase. 
      Such custom local type throws must be some custom std::status_code<DomainType>,which can implicitly decay to std::error upon demand.
      
      Under P1095, status codes knowhow to throw themselves as a non-deterministic exception upon request.As std::error is also a std::status_code<erased<T>>, deterministic exception throwingfunctions would always throw somestatus_code. 
      Hence we can hard code C++function edition semantics around those ofstatus_code:

      Я же говорю: ахтунг, ахтунг! Крестухи в комитете.
      Ответить
      • > call c++ functions

        А название руками манглить?
        Ответить
        • Ногами. И ловить багры после смены версии конпелятора, потому что у нового конепелятора мангал новый.
          Ответить
        • Лучший ответ на SO:
          echo "int f1(char *, int) {} " | g++ -x c++ -S - -o- | grep "^_.*:$" | sed -e 's/:$//'
          Ответить
          • echo "int f1(char *, int) {} " | g++ -x c++ -S - -o- | grep "^_.*:$" | sed -e 's/:$//' | c++filt
            Ответить
            • Зачем? Зачем?
              Ответить
            • Тип результата обрезается, потому что в крестах нет перегрузки по типу возвращаемого значения.

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

                Ага. А когда хочешь написать без типа, валится ошибка
                <stdin>:1:15: error: ISO C++ forbids declaration of ‘f1’ with no type [-fpermissive]
                Ответить
            • Начал гуглить, как дела в других конпеляторах.

              Нашёл вот это: https://github.com/mooware/msvcfilt

              «A similar tool, undname.exe, is already part of the Visual C++ build tools. I only became aware of undname after I had developed msvcfilt, otherwise I probably would have just used undname.»

              Какой багор )))
              Ответить
              • Ещё нашёл вот это:
                http://zed.0xff.me/2013/05/06/demangle-msvc-delphi-and-c-builder-mangled-function-names-with-pure-ruby


                А в обратном направлении, похоже, умеет только компилятор...
                Ответить
        • У «Шланга» в библиотеке есть класс, который умеет манглить:
          https://clang.llvm.org/doxygen/classclang_1_1MangleContext.html
          Ответить
        • Ещё кое-что нашёл:
          https://blog.oakbits.com/how-to-mangle-and-demangle-a-c-method-name.html
          Ответить

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