1. C++ / Говнокод #14387

    +17

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    #include <iostream>
    
    int main(){
        int std = 10;
        std::cout << std << std::endl;
    }

    Запостил: crastinus, 19 Января 2014

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

    • Сознание немного расширилось...
      А ведь когда-то давно такие моменты давали сильную встряску, и вырывался изумлённый возглас "И даже так можно?!". Сначала это было знакомство с реентерабельностью, потом - возможность изменения аргументов функции внутри неё, потом тернарный оператор, в выражении в качестве lvalue.
      Ответить
      • >о с реентерабельностью,
        Ты имеешь ввиду рекурсивные функции?

        > возможность изменения аргументов функции внутри не
        Так себе паттерн: лучше так не делать. Если конечно тебе явно не передали их по указателю или ссылке.

        Но правда это зависит от языка.

        > потом тернарный оператор, в выражении в качестве lvalue.
        А помнишь свои ощущения, когда понял, что в С++ можно так:
        foo.bar() = 42

        ?
        Ответить
        • В некоторых Бейсиках можно было так:
          LET S$ = "ПИТУХ"
          MID$(S$, 2, 1) = "Е"
          PRINT S$ ' выведет слово ПЕТУХ
          Ответить
    • А в чём прикол то? Ну 10 выводит(на ideone).
      Ответить
      • Ну, видимо, автор узнал, что имена неймспейсов и переменных лежат в разных, кхм, неймспейсах.
        В крестах каждый день что-то новое можно узнавать, даже если с ними работаешь уже лет 5-10.

        О сколько нам открытий чудных
        Готовит крестоблядский код.
        Ответить
        • Например, что они...не нужны
          Ответить
          • Не нужны - не юзай ;)
            Ответить
          • Уникалоностью плюсов в том, что они до сих пор нужны.

            Понимаете?
            Десять лет я слышу, что плюсы не нужны, а они всё еще нужны.

            Пройдут года, прибой времени смоет помойную пену -- всех этих опотных программистов на "джаваскрипт" вкотившихся в ойтишечку за длинным рублем, а стоящие программисты на настоящих языках типа "C" и "C++" этого и не заметят.

            Они будут читать в новостях "Хуюгл лейэфнул 300 000 программистов на пайтон". Читать, и посылать патч
            Ответить
        • Это мизантропия. Человек просто ненавидит тех. что будет его код сопровождать. Например
          Ответить
        • > лежат в разных, кхм, неймспейсах.
          такой ереси от тебя не ожидал ;)
          Компилятор это позволяет, потому, что для него неймспайс, это что написано после слова неймспайс, или стоящее перед ::.

          namespace nmsp;
          nmsp::var..

          А код ниже уже работать не будет, тк структура для компилятора это тоже набор символов, как и неймспейс.

          #include <iostream>

          struct std{
          static int m;
          };

          int std::m=10;

          int main {
          std::cout << std::m << std::endl;
          }
          Ответить
          • >> лежат в разных, кхм, неймспейсах.
            > такой ереси от тебя не ожидал ;)

            всё борманд правильно сказал.
            Ответить
            • Да, про неймспайсы это факт. Они и правда лежат в разных неймспайсах. Правильно будет так: "имя неймспайса можно использовать как имя переменной".
              Ответить
            • понятия "неймспейс" и "неймспейс" оказались в одном неймспейсе, и потому клашнулись
              Ответить
          • struct lol { int lol; };
            
            int main()
            {
                lol lol;
                return lol.lol;
            }
            Имена типов и имена переменных лежат у компилятора в разных "неэмспейсах". То, что определено как namespace по сути является особой разновидностью типа. Нельзя иметь тип и нэймспейс с одинаковыми именами.
            Ответить
            • > по сути является особой разновидностью типа
              Как это противоречит тому, что написал я?
              Ответить
              • Как это противоречит тому, что написал борманд? Борманд, имхо, гораздо яснее выразил мысль.
                Ответить
          • Под неймспейсом я имел в виду не ту штуку, которая в крестах называется неймспейсом, а более общее понятие, никак не связанное с крестоблядствами (прочитай про отличия LISP-1 от LISP-2, суть примерно такая же). Т.е. имена крестоблядских неймспейсов лежат в одном, кхм, пространстве имен (не путать с крестоблядским namespace!), а имена переменных - в другом. И они никак не пересекаются, т.к. компилятор знает, в каком контексте используется одно, а в каком другое. Впрочем Роман уже все разжевал на примере жабы.

            Кстати забавно, но пространство имен типов и пространство имен namespace'ов пересекаются - компилятор не даст назвать тип и неймспейс одинаково.
            Ответить
            • Да, уже понял.
              Ответить
            • > лежат в одном, кхм, пространстве имен
              наверное, можно говорить "таблица символов", чтобы не создавать коллизий

              > пространство имен типов и пространство имен namespace'ов пересекаются
              Да мне кажется, корни растут из того факта, что раньше пространсва имён реализовывали через создание пустого класса со статическими методами и вложенными классами.
              Ответить
              • >реализовывали через создание пустого класса со статическими методами
                а не из-за того, что они могут использоваться подобным образом?
                Ответить
                • > а не из-за того, что они могут использоваться подобным образом?
                  И поэтому тоже. Борманд чуть ниже пояснил.
                  Правда, есть и отличия: в классах все члены видны всем остальным, т.е. можно использовать методы до их объявления. В нэймспейсах это не работает.
                  Ответить
              • А ну да, туплю я, синтаксис то такой же. И если мы назовем класс и неймспейс одинаково - возникнет неоднозначность:
                class foo {
                    class bar {}
                };
                namespace foo {
                    class bar {}
                }
                foo::bar b; // foo::bar or foo::bar!?
                Ответить
        • В "PHP" всё более-менее предсказуемо.
          Ответить
    • Представим, что Вася написал свою библиотеку, и поместил её в неймспейс awesome,
      а Петя - свою, в которой ничего не зная про Васю, использовал слово awesome как счетчик цикла.
      И вот тут Акакий Дододжонович берёт эти обе библиотеки и пытается ском... ЧИТАТЬ ДАЛЕЕ >>>
      Ответить
      • А если бы Петя назвал awesome структуру?
        Ответить
        • если он сделал это в глобальном неймспейсе, то он ССЗБ.
          Ответить
          • Эээ, а счетчик цикла что, считается объявленным в глобальном неймспейсе?
            Ответить
            • >> Петя назвал awesome структуру?
              > счетчик цикла

              Не выспался?
              Ответить
              • В исходном комментарии говорится про то, как Петя назвал счетчик цикла awesome и он не конфликтует. На это я ответил, что если бы назвал так структуру то это бы не помогло. На что мне отвечают что со структурами все в порядке, они в именованных неймспейсах. Вывод?
                Ответить
                • Вот теперь я понял, о чём речь.
                  Но автор поста как раз удивляется, что локальные переменные и "глобальные" нэймспейсы можно называть одинаково и использовать одновременно. Если бы это не выполнялось, то сценарий, описанный @defecate-++, был бы вполне реальным.

                  Если бы Петя использовал локальную структуру std, у него бы тоже было бы всё ок: его структура скрывала бы пространство имён std внутри его кода (правда, внутри вложенных в функцию структур не может быть статических членов). Но тогда нельзя было бы написать код, подобный коду в топике, без явной квантификации
                  int f() {
                      struct std {
                          int x;
                      };
                  
                      ::std::cout << "x: " << sizeof(std::x) << ::std::endl;
                      return 0;
                  }
                  . Если Петя вложил структуру в неймспейс, то всё тоже ок, можно квалифицировать.

                  Если же Петя назвал глобальный тип также, как Вася назвал свой нэймспейс, вот тут беда.
                  Ответить
                  • > Если же Петя назвал глобальный тип также, как Вася назвал свой нэймспейс...
                    ... то оно просто не скомпилится ;)

                    gcc выдавало что-то типа error: redefining to another kind of symbol
                    Ответить
                    • > то оно просто не скомпилится
                      Да, Акакий Дододжонович будет очень огорчён. Хотя у него и сейчас есть выход:
                      namespace fucking_petya {
                      #include "petya_petushok.h"
                      }
                      Ответить
                      • А точно прокатит? В этой единице компиляции имена будут fucking_petya::petushnya, а в петиной - ::petushnya. Имхо на линковке завалится, если хотя бы одну функцию оттуда заюзать. Ну или я сегодня совсем туплю, и мне пора спать...
                        Ответить
                        • Да, это прокатит только с header-only либами :(
                          Ответить
                          • Да даже с ними не прокатит, т.к. Петя наверняка ещё много чего наинклюдил. В общем, наш Акакий вынужден форкать и править либу Пети. Судьба у него такая.
                            Ответить
                  • >Но автор поста как раз удивляется
                    как удивительно, что в языке с полнотой по тьюрингу времени компиляции творятся такие удивительные вещи с именами.
                    Ответить
                    • А как эти вещи связаны с полнотой по тьюрингу?
                      Ответить
                      • ИМХО никак.
                        Ответить
                      • Это о фичах в плюсах.

                        Так и знал, что нужно зеленым писать.
                        Ответить
                        • Интересно, есть хоть один человек, который знает с++11 полностью, и может объяснить с первого раза любой встретившийся ему момент?)
                          Ответить
      • Мне вот что интересно а разве в крестах нельзя все переменные которые используются локально объявить так что бы их не было видно глобально ?
        И другой вопрос в неймспейсе моджнили обявлять вложенные неймспейсы ?
        Ответить
        • > все переменные которые используются локально Объявить так что бы их не было видно глобально?
          моя не панимать. Работают нормальные области видимости. Всё, что внутри функции, снаружи не видно. Стек же.
          Если хочется глобальные для модуля переменные (не видимые другим модулям), есть волшебное слово static или анонимный неймспейс.

          > в неймспейсе моджнили обявлять вложенные неймспейсы?
          моджни.
          Ответить
          • > моджни.
            Но тем не менее, иерархии неймспейсов нет. Есть только линейное пространство имен пространств имен.

            Или я сегодня туплю?
            Ответить
            • иерархия есть, когда компилятору надо найти ближайшее соответствие имени - ему надо идти по дереву вверх
              Ответить
              • Да, мне пора на покой. Спутал с жабьими пакетами, где иерархии действительно нет, и com.sun.java.fuck это всего лишь длинное имя :(

                А в крестах мало того что вверх умеет идти, так еще и после using namespace foo можно будет вместо foo::bar::test писать просто bar::test... Все-таки иерархия есть.
                Ответить
              • >Представим, что Вася написал свою библиотеку, и поместил её в неймспейс awesome,
                а Петя - свою, в которой ничего не зная про Васю, использовал слово awesome как счетчик цикла.
                И вот тут Акакий Дододжонович берёт эти обе библиотеки и пытается ском... ЧИТАТЬ ДАЛЕЕ >>>

                Ну тогда это вообще не возможная ситуация. Каждый разработчик либ фигачет свой неймспейс и в нем ебется конем как ему хочется, всякие счетчики цикла и фигушки которые должны умереть внутри умирают внутри модуля, все, что должны выйти наружу выходит в неймспейсе. И тогда никаких пересечений с именами не будет.
                Ответить
        • > разве в крестах нельзя все переменные которые используются локально объявить так что бы их не было видно глобально ?
          вроде бы можно заключить в безымянный namespace

          > в неймспейсе моджнили обявлять вложенные неймспейсы ?
          судя по бусту, можно
          Ответить
        • На самом деле есть даже мега-удобная фича с алиасингом неймспейсов.
          namespace fs = boost::filesystem;
          
          if (fs::exists(my_file)) do_happiness();
          Ответить
        • во-первых, это надо умудриться переменную объявить глобально - порочная практика даже во времена С
          во-вторых, такие проблемы могли бы возникнуть при компиляции именно петиного кода, а не васиного - но такого конфликта даже нет
          и в третьих, если у пети есть свой неймспейс, то вообще становится крайне сложно организовать проблемы, о которых стоило бы переживать - было бы неплохо, если бы кто-то смог предложить пример конфликта
          а в подтверджении моих слов пока вот: http://ideone.com/9517zU

          и про второй вопрос - в неймспейсе нет ограничений на вложенные неймспейсы
          you::can::shoot::your::legs::as::you::want
          Ответить
      • То ли дело "D". Там модули есть.
        Ответить
        • Кстати, у меня к тебе вопрос: верно-ли я понимаю, что ``recv(2)``/``read(2)`` из сокета считает столько данных, сколько там есть (если их больше ноля) даже если я попросил больше данных, если только не установлен ``MSG_WAITALL``, а например чтение из pipe может заблокироваться если данных меньше буфера?
          Ответить
          • > верно-ли я понимаю, что ``recv(2)``/``read(2)`` из сокета считает столько данных, сколько там есть (если их больше ноля) даже если я попросил больше данных, если только не установлен ``MSG_WAITALL``, а например чтение из pipe может заблокироваться если данных меньше буфера?

            recv() с pipe вообще не работает, и в read() никакого "MSG_WAITALL" нет. Из pipe чтение через read() заблокируется, если в пайпе нихуя нет. Если хоть один байтик есть, он и прочтется. Из сокета еще можно получить датаграму нулевого размера, а для pipe это хуйня полная, потому что никаких "датаграм" там нет

            https://man7.org/linux/man-pages/man2/recv.2.html#NOTES
            If a zero-length datagram is pending, read(2) and recv() with a
            flags argument of zero provide different behavior.  In this
            circumstance, read(2) has no effect (the datagram remains
            pending), while recv() consumes the pending datagram.
            Ответить
            • > the datagram remains pending

              Хм, т.е. прога тупо повиснет навсегда т.к. read() не может избавиться от пустой датаграммы?
              Ответить
              • read() ее просто пропустит. А когда будет непустая датаграма, он уже прочитает.

                Можешь написать какую-нибудь хуйню на сокетах и проверить.
                Ответить
                • Хм, или у меня лапки, или ман пиздит...

                  read() на UDP сокете тоже вернул 0 при получении пакета нулевой длины. Ну и собственно убрал его из буфера.
                  Ответить
                  • read() на UDP при попытке чтения чего-то нулевой длины - сразу завершается, не дожидаясь каких-то "пакетов". recv() же будет ждать некую хуйню
                    #include <stdio.h>
                    #include <stdlib.h>
                    #include <unistd.h>
                    #include <string.h>
                    #include <sys/types.h>
                    #include <sys/socket.h>
                    #include <arpa/inet.h>
                    #include <netinet/in.h>
                      
                    #define PORT     8080
                    #define MAXLINE 1024
                    
                    int main() {
                        int sockfd;
                        char buffer[MAXLINE];
                        char *hello = "Hello from server";
                        struct sockaddr_in servaddr;
                    
                        // Creating socket file descriptor
                        if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
                            perror("socket creation failed");
                            exit(EXIT_FAILURE);
                        }
                    
                        memset(&servaddr, 0, sizeof(servaddr));
                    
                        // Filling server information
                        servaddr.sin_family    = AF_INET; // IPv4
                        servaddr.sin_addr.s_addr = INADDR_ANY;
                        servaddr.sin_port = htons(PORT);
                    
                        // Bind the socket with the server address
                        if ( bind(sockfd, (const struct sockaddr *)&servaddr, 
                                sizeof(servaddr)) < 0 )
                        {
                            perror("bind failed");
                            exit(EXIT_FAILURE);
                        }
                        //ssize_t n = read(sockfd, buffer, 0);
                        ssize_t n = recv(sockfd, buffer, 0, 0);
                        printf("recvd %zd\n", n);
                    
                        return 0;
                    }

                    Переделал https://www.geeksforgeeks.org/udp-server-client-implementation-c/
                    Ответить
                  • В общем суть в том, что если через read читать ноль байтиков, нихуя вообще не будет, оно пропустится, а вот recv будет ждать хуйню, и захавает какую-то датаграму из сокета
                    Ответить
                    • А, так надо именно ноль байт читать (что для read, судя по его ману, не имеет смысла и вообще implementation defined), только тогда будет разница?

                      З.Ы. А где в мане написано что это отличие только для size == 0? Там вроде только о длине датаграммы говорят.
                      Ответить
                      • > А, так надо именно ноль байт читать (что для read, судя по его ману, не имеет смысла и вообще implementation defined)

                        Такую тонкую питушню надо не в манах, а в каких-то юникс-спецификациях читать. И вообще, лучше не выебываться со всякими read() на сокетах, и использовать специально предназначенные recv() и recvfrom()
                        https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html#tag_16_474
                        > How read() handles zero-byte STREAMS messages is determined by the current read mode setting. In byte-stream mode, read() shall accept data until it has read nbyte bytes, or until there is no more data to read, or until a zero-byte message block is encountered. The read() function shall then return the number of bytes read, and place the zero-byte message back on the STREAM to be retrieved by the next read(), getmsg(), or getpmsg(). In message-nondiscard mode or message-discard mode, a zero-byte message shall return 0 and the message shall be removed from the STREAM. When a zero-byte message is read as the first message on a STREAM, the message shall be removed from the STREAM and 0 shall be returned, regardless of the read mode.

                        > З.Ы. А где в мане написано что это отличие только для size == 0? Там вроде только о длине датаграммы говорят.

                        Ну хуй знает, вполне возможно, что в мане они написали какую-то хуйню.
                        Ответить
                      • Может быть под "If a zero-length datagram is pending" надо понимать "если мы хотим из сокета прочитать датаграму нулевого размера".

                        recv(sockfd, buffer, 0, 0); // типа вот тут "zero-length datagram is pending"
                        Ответить
                        • Ну тогда это какая-то странная формулировка...

                          Я вот сразу подумала, что pending -- это "пришла и лежит в буфере".

                          Скорее тупо скопипастили ман с другой оси/версии, где read такое не читал, да забыли поправить.
                          Ответить
                          • а разве буркалы сокеты не должны был коньсистемны на всех платформах?
                            не за это диды в протокольной войне ваивали!
                            Ответить
                            • Посмотри на ту парашу, которую мелкомягкие в винде с беркли-сокетами сделали.
                              https://docs.microsoft.com/en-us/windows/win32/winsock/porting-socket-applications-to-winsock


                              WSAGetLastError() какой-то блядь. Я как-то переписывал хуйню на винсоксах в обычные беркли сокеты
                              Ответить
                              • Ня напоминяй. Виндовые сокеты — это такое адское забаговнное говно, что даже някать ня хочется (ノ°益°)ノ.
                                Ответить
                              • Там ещё есть функции, которые на вход принимают дескриптор окна. Окна для сокетов!
                                Ответить
                                • Это для поддержки RFC 1149 (⌒▽⌒)☆.
                                  Ответить
                                  • Кстати, его же вроде испытали, и даже что-то смогли передать, если я не ошибаюсь.
                                    Ответить
                                    • Если передавать флешки большого объёма одновременно несколькими голубями, получим LFN = long fat network. Сеть с большой скоростью передачи, но при этом с длинным пингом. Почти как спутниковая связь.
                                      Ответить
                                      • Камаз с ДВД, облегченная версия.
                                        Ответить
                                      • Можно кучу голубей с какой-нибудь миниатюрной радиохуйней выпустить, и сделать mesh-сеть поверх них.
                                        Ответить
                                        • Голуби обычно собираются в стаи. В одной стае mesh-сеть не нужна, а между разными стаями может быть слишком большое расстояние.
                                          Ответить
                                          • голубцам надо не мешать
                                            их в стаи сгоняет прошивка
                                            https://www.youtube.com/watch?v=86iQiV3-3IA
                                            Ответить
                              • падажжи, WSA это суперсет, переписывание неизбежно что-то обрежет

                                и вероятно дохуя, томущо A это асинхронные
                                Ответить
                                • > и вероятно дохуя, томущо A это асинхронные

                                  WSA это "Windows Sockets API", где там "асинхронные"?
                                  Ответить
                                  • Как ты хорошо лалку слил
                                    Ответить
                                  • Потому что асинхронность завезли в винду именно ради сокетов.


                                    Смотри: во времена Win16 многозадачность была кооперативной. Чтение из файла блочило весь мир, но файлы были близко.

                                    Чтение из клавы не было по сути IO, потому что поступало как сообщение в event loop.

                                    А как быть с сетью? Нельзя лочить же (сеть далеко) и потому сделали асинхронный API.

                                    А вот потом уже на всю винду распостранили
                                    Ответить
                                    • В 3.x даже была елда (функция Yield), чтобы отдать тики другим задачам.
                                      Ответить
                                      • да, хотя основной точкой было `GetEvent()`

                                        Там еще была смешная API: пока WinSock ждёт -- он мог крутить события, и вызывать твою функциб для прогрес-бара

                                        короче, асинхронное программирование это всегда шарик-лизун с налипшими на него волосами

                                        Ей богу, корутины это relief
                                        Ответить
                                        • Но елда звучит смешнее. Как я понял, после неё всё равно придётся вызывать GetEvent, чтобы освободить очередь сообщений.
                                          Ответить
                                          • Мне моя елда на исходе дня
                                            Пропоёт о том, что любовь прошла.
                                            Ответить
                                            • не надо со своей елдою разговаривать, и слушать её не надо
                                              Ответить
                                • select() есть, вместо poll() какой-то WSAPoll()
                                  https://habr.com/ru/post/105918/

                                  Ну и еще есть какая-то чисто виндоспецифичная говнина с overlapped I/O, но в том коде этой говнины не было.
                                  https://docs.microsoft.com/en-us/windows/win32/winsock/overlapped-i-o-and-event-objects-2
                                  Ответить
          • > ``recv(2)``/``read(2)`` из сокета считает столько данных, сколько там есть (если их больше ноля)

            Я относительно давно с этими сокетами связывался, но там есть такая хуйня, что если UDP (SOCK_DGRAM) то ты прочитаешь один пакет. Т.е. если тебе прилетело два пакета по 10 байт, и они там где-то хранятся во внутреннем буфере ОС, то даже если ты дохуя хочешь прочесть, ты первым recv() прочитаешь 10 байт, вторым recv() прочитаешь еще 10 байт.

            К тому же "MSG_WAITALL" тоже не гарантирует, что у тебя столько прочитается, сколько ты запросил. См https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
            >MSG_WAITALL
            > On SOCK_STREAM sockets this requests that the function block until the full amount of data can be returned. The function may return the smaller amount of data if the socket is a message-based socket, if a signal is caught, if the connection is terminated, if MSG_PEEK was specified, or if an error is pending for the socket.
            Ответить
            • Кстати вот еще обрати внимание
              https://stackoverflow.com/a/2862176

              What happens if recv gets a packet larger than the buffer?

              SOCK_STREAM: The question doesn't really make sense as put, because stream sockets don't have a concept of packets - they're just a continuous stream of bytes. If there's more bytes available to read than your buffer has room for, then they'll be queued by the OS and available for your next call to recv.

              SOCK_DGRAM: The excess bytes are discarded.
              Ответить
    • Как я попал в этот оффтоп?
      Ответить
      • А как я в него попал?
        Ответить
        • Увидел в стоке мой комментарий и захотел узнать в какой же тред я попал.
          Ответить
          • Откуда зняешь?
            Ответить
            • Идут Шерлок Холмс и доктор Ватсон по Бейкер-стрит. Шерлок Холмс говорит:
              - Э-э, дружище Ватсон, могу с уверенностью сказать, что вон за тем углом вам ввалят хороших п%%дюлей.
              Доходят до того угла и, дейтвительно Ватсону там хорошо достается от двух здоровых лбов.
              - Как Вы узнали про это, Холмс?
              - Элементарно, Ватсон, я здесь вчера в вашем пальто вы%%ывался...
              Ответить
      • Нужно позвонить в "Необъяснимо но факт" с таким вопросом.
        Ответить
        • Ну как, позвонил?
          Ответить
        • Нужно звонить в скорую ПСИХИАТРИЧЕСКУЮ помощь: такая тоже имеется!


          Недавно пересмотрел "черная роза -- эмблема печали", кстати. Какой всё таки охуенный фильм. Толик-с-прибором мой герой
          Ответить
    • C:\Gebruikers\Johan\Mijn afbeeldingen\Zonnebloem.jpg
      Ответить

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