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

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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 j123123, (Updated )

Комментарии (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-шникам на Си?

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

              Хуеволюция
              Ответить
              • Не хочу прерывать ваш диалог, но не насрать ли?
                Ответить
                  • Можете договориться в своей команде не использовать эту хуйню, если это хуйня.
                    Ответить
                • Так нельзя зделать?
                  file1 = dfopen("a_file", "w"); //    auto defer(fclose, file1);
                      if (file1 == NULL) {
                        return -1;
                      }
                  Но это уже попахивает деструкторами, да.
                  Ответить
              • >позволяют привязывать высвобождение ресурсов к лексическим областям видимости переменных или, проще говоря, вызывать какой-то код с выходом программы из области видимости переменной.

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

            Что мешает сделать такой struct сейчас, не меняя язык?
            Ответить
            • придется исправить примерно все функции, и заставить их возвращать, нет?

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

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

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

        Кстати, что там с union и кастами pituz* -> void* -> other_pituz*? Их хоть починили?
        Ответить
        • > и кастами pituz* -> void* -> other_pituz*

          А что ты там предлагаешь чинить?
          Ответить
          • Если там нельзя положить одну питушню, а достать другую без подвохов, то это надо чинить. Скажем, чтобы можно было взять любую пару типов char[4], int32_t и float и читать-писать их. И чтоб без UB, внезапных паддингов, выравниваний и *конечников.
            Ответить
        • >Язык очищают от говна и питушни в поведении.

          Про ECMAScript тоже так говорили.
          Итог будет примерно такой же.
          Ответить
  • > Включение двоичных файлов в исходный файл

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


    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)();
        }
        Ответить
          • А погуглить строки лень? Или ДИЗАССЕМБЛИРОВАТЬ? Это 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. Нужно еще секцию указывать
                Ответить
                  • Может быть это стандартизируют, и будет один конкретный способ указывать, в какую секцию какую хуйню пихать.
                    Ответить
                    • На уровне языка можно стандартизировать синтаксис прагм. На уровне платформ стандартизировать названия секций не получится. В «Windows» и в «UEFI» используется формат «PE», в «Линуксе» — «ELF», в «Mac OS X» — «Mach-O»...

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

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

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

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

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

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

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

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

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

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

        Экономии никакой, даже больше кода чем просто в конце вызвать fclose(file2).
        Ответить
        • А вообще да. Как только стройную и простую как пробка конструкцию начинают шатать, тут-то ей пизда и приходит.

          defer для закрытия файлов? А для освобождения памяти тоже? А если передал ресурс в другое место, то может туда еще и счетчик встроить? Опа, вот и рефкаунтер пожаловал. Ну итд
          Ответить
          • Ручной defer нинужен. Ничего полезного он не добавляет и его можно забыть позвать. С тем же успехом я могу написать goto в конец функции и там всё позакрывать.
            Ответить
            • ну это же попытка освободить неавтоматический ресурс при выходе из блока

              Слушайте! а почему из всех ресурсов автоматическим в няшной бывает только память?
              Почему нельзя закрывать файл при выходе из ресурса, освобождать какой-нить мютекс там, секцию, пайпу и пр.
              Я не про RAII сейчас, а про сишку.

              Почему

              int petuh; очистится, а файл нет?
              Ответить
              • > int petuh очистится

                Потому что он не очищается. В нём остаётся мусор до следующего использования этой ячейки или регистра. В сишке вообще ничего не очищается и не освобождается само по себе.
                Ответить
                • ну не буквоедствуй. Я имею право его явно не чистить. Стек схлопнется, и всё.
                  Почему нельзя так же закрывать файл? Не надо только про имплементацию говорить, я чисто с семантической точки зрения (почему закрыть файл в стопицот раз дороже чем просто подвинуть SP я понимаю)
                  Ответить
                  • Потому что для схлопывания стека ничего делать не надо. Восстановил esp и всё.

                    А для закрытия файла или освобождения кучи надо что-то позвать. А что именно надо позвать? А хуй знает, никто компилятору это не объяснил. А надо ли звать вообще? Вдруг я хочу оставить файл открытым? И это тоже конпелятору никто не объяснил.
                    Ответить
                    • ну то-есть дело всё таки в сложности имплементации?
                      > Вдруг я хочу оставить файл открытым?
                      тогда открывай его "в куче", лол

                      блядь, я сейчас реально С++ с RAII переизобрету.
                      Ответить
                      • Скорее в сложности языка. Сейчас control flow у сишки максимально тупое и понятное (если отбросить longjmp). Для управления ресурсами же понадобится куча новых конструкций и инфы.

                        Видимо поэтому и добавили ручной defer на отъебись.
                        Ответить
                        • >longjmp
                          setjmp нужен чуть менее, чем никогда. Разве что для SEH.

                          >на отъебись.
                          а зачем?

                          Если я всё равно должен его руками заполнять, то лучше я правда сделаю goto и явно всё почищу. А иначе я что-нить проебу, ну и флоу станет мутнее
                          Ответить
                          • > а зачем

                            Да хер знает. Видимо любители портянок их уломали чтобы defer(close) писать рядом с open'ом, а не через 10 экранов...
                            Ответить
                            • Сиречь я по всей портяночке собираю в коробочку хендлы от malloc, fopen и пр, а в конце все их одним махом очищаю?
                              а в каком порядке? fifo?
                              Ответить
                                • да, ты прав.

                                  В общем Defer сразу задает очень много вопросов, и может привести к сильному усложнению сишечки

                                  А сложная сишечка не нужна.
                                  Единственное её преимущество в простоте
                                  Ответить
                                  • Ну Шляпа пролезла в комитет, и давай умничать: 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.
                                      Ответить
                                      • Да и на симбиане такой пул был, хоть там формально и кресты.
                                        Ответить
                                      • Блять. Я уже начинаю уважать СиПлюсТрупа с его 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){
                              }

                              Иначе питущня.
                              Ответить
                              • а можно
                                char code;
                                int err = get_code(&code);
                                if (err = CODE_OK) {
                                printf("%c", code);
                                } else {
                                //
                                }
                                Ответить
                                  • можно
                                    так зачем тогда возврат нескольких пельменных?

                                    Кстати, в C# так можно тоже.
                                    А вот в Java нельзя без лишних расходов
                                    Ответить
                                    • Хуиту какую-то городят стандартизаторы.

                                      На одно полезное изменение (typeof), 3 ни о чём, 3 вредных, и 3 безумных.
                                      Ответить
                                    • Кстати, а как сделать аутпараметр в C++ для сложного класса? Никак?

                                      Кресы соснули у шарпея что-ли, или просто я еблан?
                                      Ответить
                                      • Поясню мысль.
                                        Заполнять простые структуры мы умеем
                                        class SomeClass
                                        {
                                        public:
                                        	int foo = 42;
                                        };
                                        
                                        void Foo(SomeClass* outParam)
                                        {
                                        	outParam->foo = 33;
                                        }
                                        
                                        
                                        int main()
                                        {
                                        	SomeClass a;
                                        	Foo(&a);
                                        	return 0;
                                        }
                                        .
                                        Но что, если я хочу, чтобы Foo сам создал объект?

                                        В C# пескоку все через кучу, всё просто
                                        static class Program
                                            {
                                                class SomeClass
                                                {
                                                    
                                                }
                                        
                                                static bool Foo(out SomeClass a)
                                                {
                                                    a = new SomeClass();
                                                    return true;
                                                }
                                                static void Main()
                                                {
                                                    SomeClass a; //Reference/Pointer. No ctor called.
                                                    Foo(out a); // Now points to some obj in the heap
                                                    
                                                }
                                            }
                                        .


                                        По идее я мог бы хотеть чтобы в си:
                                        * выделили память на стеке
                                        * передали указатель на неинициализорванную память в Foo
                                        * Foo заполнила бы ее констрнуктором

                                        Или так не бывает? Или нельзя память, а потом конструктор, можно только через указатель, но вручную?
                                        Ответить
                                        • Вроде как в сишке принято самому выделять память под структурку, забивать ее нулями, а потом давать указатель на нее в функцию инитиализации.
                                          Ответить
                                        • Ну обычно у объектов есть дефолтный конструктор, поэтому просто присваиваешь поверх старого:
                                          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 извратиться, но никто так не пишет.
                                          Ответить
                                          • я не хочу два раза конструктор вызывать жи. Вот move -- ок. То-есть до с++11 было только через поинтер?
                                            Ответить
                                            • Дык дефолтный коньструктор обычно ничего особенного и не делает, это как инициализация нулями в сишке.
                                              Можно, конечно, как Борманд предложил — с «placement new», но это так-то багор: как минимум, тебе потом придётся руками вызывать деструктор.
                                              Ответить
                                              • guest8 видимо о том, что конструктор копирования для передачи параметров через out был неизбежен до с++11. А для сложных объектов это действительно жопа. Многие из них в принципе не копируются.
                                                Ответить
                                                • да, именно так.

                                                  А вот в C# это красиво решено
                                                  Ответить
                                              • если он ничего не делает, то я могу создать что-то на стеке, и передать по ссылке, и пусть заполнят

                                                А я говорю про тяжелые конструкторы жи
                                                Ответить
                                                • Дефолтный конструктор в 99% случаев нихуя не делает. Поэтому можешь смело создавать на стеке, передавать по ссылке и просить заполнить.
                                                  Ответить
                                                • …А если дефолтного конструктора нет (или он есть, но открывает соединение с «MySQL» и считает последнюю цифру числа «Пи»), уко-ко-ко-затели использовать не хочется (лучше, кстати, по-умолчанию использовать unique_ptr — тогда у пользователей, которым shared_ptr не нужен, не будет лишних расходов, а кому нужен — те просто сделают «shared = std::shared_ptr(unique);»), то просто развращай std::pair/std::tuple и не нагружай моск.
                                                  Ответить
                                                  • > то просто развращай std::pair/std::tupl
                                                    и налетай на еще один копирующий консмтруктор? или там копи элижен сработает?
                                                    Ответить
                                                    • Сработает. Если не хочешь пердолиться — пару можно сконьструировать при возврате, тогда оверхед будет в один перемещающий коньструктор и один деструктор: https://wandbox.org/permlink/I1IMj1yQQnrsM9ON. Если надо м-м-максимум пирфоманса — сразу коньструируй пару, тогда получится зирокост: https://wandbox.org/permlink/ow5nRVLO7wBD46hO.
                                                      Ответить
                                                      • Вот интересно: Хорошая вроде-бы идея: совместить инициализацию с конструктором, и не давать пользователю иметь заполненную хуями память.

                                                        Но сколько сразу "тонких" моментов повылазило, а?

                                                        Копирование, перемещение, элизия этого, брр
                                                        Ответить
                                                        • Это всё из-за жизненного цикла объектов в крестах: объект может быть либо инициализированным, либо не существовать вовсе.
                                                          Конечно, можно было бы «для простоты» ввести неинициализированное состояние объекта, но если копнуть поглубже — такие багрища вылезут, что копирование-перемещение покажется простым и понятным механизмом.
                                                          Ответить
                                                          • Вот хуй знает.
                                                            Расклейка инициализации и конструирования (как в няшной) сильно упростила бы ситуацию.

                                                            Но тогда нужно гарантировать, что "внешние" чуваки не обратятся к неинициализированному объекту. Не очень понятно, как это сделать.

                                                            Типа
                                                            Petuh std:alloc_mem(petuz);
                                                            InitializePetuh(petuz); //
                                                            //////
                                                            
                                                            [AllowAccessUnitilizaed<Petuh>]
                                                            void InitializePetuh(uniniailized_ref<Petuh> petuz) {
                                                            // Trust me, I am initializer!!
                                                            petuz.foo = 24;
                                                            }


                                                            С немутабильными объектами воощей хуйзнает что делать
                                                            Ответить
                                                            • Думаю, самым сложным будет автоматический вызов деструктора. Так-то расклеить инициализацию и коньструирование можно и сейчас:
                                                              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.
                                                                              Ответить
                                                                          • Печально, что даже в котлине это не пофиксили.

                                                                            Хвалёный nullability safe наёбятывается на раздватри
                                                                            fun bar(foo: Foo) {
                                                                                foo.s.toString() //NPE, ахахаха
                                                                            }
                                                                            
                                                                            class Foo {
                                                                                val s:String
                                                                            
                                                                                init {
                                                                                    bar(this)
                                                                                    s = "A"
                                                                                }
                                                                            }
                                                                            
                                                                            fun main() {
                                                                                Foo()
                                                                            }
                                                                            Ответить
                                                                • Неважно, 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();
                                                                    }
                                                                    .

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

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

                                                                    лучше тока было сразу кастануть, и в инициализтора принимать уже указатель на петуха
                                                                    тае понятнее
                                                                    Ответить
                                                                    • а бывает displacement delete, лол?
                                                                      delete (kuratnik) petuh;

                                                                      Всё равно конечно все соснули у C#:
                                                                      struct Foo
                                                                          {
                                                                              public int Iq { get; }
                                                                      
                                                                              public Foo(int i)
                                                                              {
                                                                                  Console.Write("Created");
                                                                                  this.Iq = i + 1;
                                                                              }
                                                                      
                                                                          }
                                                                      
                                                                      
                                                                          static class Program
                                                                          {
                                                                              static void Init(out Foo foo)
                                                                              {
                                                                                  foo = new Foo(13);
                                                                              }
                                                                      
                                                                              static void Main()
                                                                              {
                                                                                  Foo foo;
                                                                                  Init(out foo); //О, как!
                                                                                  Console.Write(foo.Iq);
                                                                              }
                                                                          }


                                                                      Правда конечно проблес с деструктором тут нет.
                                                                      У классов он всё равно вызовется в ГЦ, а у структур (в данном примере Foo живет на стеке Mainа) их не бывает
                                                                      Ответить
                                                                      • > а бывает displacement delete, лол?
                                                                        Не, не завезли. Только ручками сначала звать деструктор, а потом удалять память (по указателю того типа, который изначально создавался через new).
                                                                        Ответить
                                                                        • В моём случае не надо ничо удалять, потому что этот ваш aligned_storage у меня на стеке же. Достаточно вызвать деструктор
                                                                          Ответить
                                                                          • Да, именно. А delete в крестах — это всё же про освобождение выделенной в куче памяти.
                                                                            Ответить
                                                                            • Подумал, как сделать alignment вручную красиво.

                                                                              Создаю массив char[sizeof(Petuh)], но теперь мне надо, чтобы он начинался на адрес, кратный alignof(Petuh), верно?

                                                                              Кстати, alignof разве не должен совпадать с sizeof на x86?

                                                                              Могу конечно найти место в массиве, где % alignof(Petuh) == 0, и передать укзаатель на него в new(). Но может я могу сразу создать массив с нужным смещением? Есть в си такое?
                                                                              Ответить
                                                                              • Можно std::align() заюзать, чтобы точно не багриться с баграми про кратность.

                                                                                > Кстати, alignof разве не должен совпадать с sizeof на x86?
                                                                                Дык в «x86» нет никаких «struct»/«class», там только байты/слова/двойные слова/четверные слова.
                                                                                Ответить
                                                                                • >Можно std::align() заюзать, чтобы точно не багриться с баграми про кратность.

                                                                                  я помнимаю, но я хотел вручную.

                                                                                  >Дык в «x86» нет никаких
                                                                                  был такой совет от интела: чтобы не ебаться, выравнивайте всегда в памяти данные по их размеру.

                                                                                  Байт ложите где угодно.
                                                                                  Два байта -- по четным адресам.
                                                                                  Структуру размером 100500 байт ложите по адресу, кратному 100500

                                                                                  Или я путаю?
                                                                                  Ответить
                                                                                  • > Или я путаю?
                                                                                    Не знаю, я не настолько глубоко погружался в x86. Но в общем-то звучит логично.
                                                                                    Впрочем, конкретно с крестами это не работает: в них выравнивание по Стандарту может быть только степенью двойки (включая нулевую степень — для char).
                                                                                    Ответить
                                                                                  • А если у массива элемент размером 5 байт, то его нужно класть по адресу, кратному 5? Звучит логично с точки зрения конпелятора (тогда адреса элементов легко считать), но бесполезно с точки зрения процессора: у процессора нет инструкции «прочитать 5-байтовое число», а есть инструкции для чтения байта, ворда, дворда, куворда. И именно инструкция чтения какого-нибудь дворда может обломаться и физически превратиться в две операции чтения, если адрес не выровнен на дворд, получим штрафные такты.
                                                                                    Ответить
                                                                                    • Скорее всего речь идет о кратности размера, выравненного до размера, кратного и ему, и степени двойки.

                                                                                      5 байт лучше хранить в ящичках по 8.

                                                                                      100 байт лучше хранить в 128.

                                                                                      100500 правда хз в чем хранить
                                                                                      Ответить
                                                                                      • А вообще огромные объекты наверное надо паковать в удобные 4К странички, да?
                                                                                        Ответить
                                                                                          • Кажется, мы на пороге открытия новой функции.
                                                                                            Ответить
                                                                                            • Ага, двойка в степени логарифм по основанию два, округлённый в большую сторону.
                                                                                              Ответить
                                                                                              • Ну вот, оказывается, всё уже придумано до нас.
                                                                                                Ответить
                                                                                                • Ничево смешново.
                                                                                                  Чем глубже в жопу -- тем больше дыры между степенями двойки, и больше оверхед.

                                                                                                  В чем мне хранить четырегигабайта и один байт?
                                                                                                  Ответить
                                                                                                    • alingof говорит о том, что хранить свой хуй тебе следует в ячейке, чей адрес кратен четырём.
                                                                                                      То-есть ты всегда кончином головки будешь залазить в соседний "блок", и наверняка триггерить загрузку говна из памяти, а то и из диска
                                                                                                      Ответить
                                                                                                  • Посетитель, случайно оказавшийся на «Говнокоде», может подумать, что это форум проктологов...
                                                                                                    Ответить
                                                                                              • То-есть если у меня есть
                                                                                                65537 байт, то я в жопке?
                                                                                                Ответить
  • Ну раз нуль терминированные строки говно - паскаль-строк этому господину. Хотя можно подизьебнутся с псевдоклассом - но то срачей будет в комитете стандартов.

    А пространств имен в и операторов типа new/delete в си так и не добавили, что жаль.
    Ответить
    • Пусть тебя не тяготит эта оказия. Будучи великомученником (а мучать я тебя буду страшно), ты попадешь прямо в рай.
      Ответить
  • >habr.com/ru/company/badoo/blog
    >>habr.com/ru
    >>company/badoo
    Да сишка фуфло.
    В стандарт никак не завезут функции, чтобы поставить like какой-то нибудь инстаграмной курице.
    Ответить
    • Сейчас должен прибежать тупой питух, и начать кукарекать, что в си нету стандатной библиотики, потому что там даже нету мапы.

      Чтобы заткнуть такого питуха, надо спросить его "а как должна быть реализована мапа?"

      Питух сразу осознает свою анскильность, заткнет клюв, и пойдет писать дальше на своем пхп
      Ответить
      • Зато в позиксе она есть. Одна на процесс, без ресайза и удаления элементов.
        Ответить
      • В Сишке мапы и сеты встроены прямо в язык. Называются «массив».
        Царь показывал:
        uint8_t set[255]={
        [A]=1
        ,[В]=1
        ,[C]=1
        };
        Ответить
      • Какой пердолинг )))

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

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

          Если мне это не важно, то я беру скриптушню.

          мапы/дикты/хеши есть (и обязаны быть) в скриптушне, а в си им, очевидно, делать нечего.
          Ответить
        • >Программистов, пользующихся удобными инструментами, пердоля называет анскильными питушками.

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

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

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

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

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

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

              Именно после таких вот принцесс, которым лишь бы код нахуярить, а как это в проде запускаться будет пусть админ пердолится, и появилась культура девочек-собачек.
              Ответить
              • а разве девочки собачки это не про то, чтобы настраивать окружения не вучную, а через конфигурейшен-аз-кодерствм?
                Ответить
                • Отчасти. На практике это про "Чего балерине^W программисту зря крутиться? Ей бы к ноге динамо-машину^W^W админство присобачить".
                  Ответить
  • 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:

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

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

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

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


    8