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

    +61.8

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    const int size=8;
    
    class Bin
    {
    public:
    	Bin();
    private:
    	char first[size];
    	char second[size];
    };
    
    Bin::Bin()
    {
    	for (int s=0;s<=size;s++, first[s]='0');
    }

    Вот вам смешно? А я пару часов думал почему при заполнении одного вектора меняется другой...

    Запостил: meriados, 23 Октября 2009

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

    • меняиццо да не весь
      но первый элмент точно
      Ответить
      • Два меняется. Когда s становится равным size, всё равно выполняется s++ (теперь s=size+1) и first[s]='0'.
        Ответить
        • А как думаешь, есть способ переписать этот код так, чтобы таких ошибок возникнуть просто не могло? ;-)
          Ответить
          • for (int s=0;s<=size;first[s]='0', s++);

            так не возникнет
            Ответить
            • for (int s=0;s<=size;first[s++]='0');
              Ответить
              • Массив создаётся от чего? От size. Что лежит в first[size]? Неизвестно что. В приведённом выше цикле s принимает значение size, что приводит к проблеме.
                Лучше всегда использовать префикс, так как он не должен создавать временное значение, чтобы его вернуть.
                Если вы используете классический С-массив, то зачем вам врЕменная переменная s?
                Ответить
              • Дык, ошибка все равно осталась :-)
                Смешно.
                Ответить
                • Чтобы ошибок не было, нужно писать на С++, а не на С. Данный код -- очередной пример "сишности".
                  Не пользуйте C-массив -- есть valarray, не заполняйте его сами -- используйте конструктор, не используйте константы -- используйте шаблоны.
                  Пишите на С++ =]
                  Ответить
                  • Абсолютно согласен. Хочу лишь добавить: как можно меньше пользуйтесь циклами -- используйте стандартные алгоритмы.
                    Вот код автора с минимальной переделкой, в котором не может быть двух найденных ошибок:

                    #include <algorithm>
                    using namespace std;

                    const int size=8;
                    class Bin
                    {
                    public:
                    Bin();
                    private:
                    char first[size];
                    char second[size];
                    };

                    void myPolicy(char& myValue)
                    {
                    myValue = '0';
                    }
                    Bin::Bin()
                    {
                    for_each(first, first + size, myPolicy);
                    }
                    Ответить
                    • А здесь можно использовать std::fill вместо for_each ;-)
                      Ответить
                  • Сколько книг по Си++ прочитал, а про valarray не знал. Спасибо.
                    Ответить
                    • Вообще странно... Дело в том, что valarray`ю посвятил отдельную главу Страуструп. valarray очень важная вещь. Только благодаря ему С++ можно применять для вычислений различных, например в теоретической физике.
                      Однако, большинству программистов valarray не нужен.
                      http://www.cplusplus.com/reference/std/valarray/
                      Ответить
                      • Да, может я и читал про него, но не запомнил, т.к. применений не было.
                        Ответить
                  • а ещё лучше - не пишите ни на C, ни на C++, а на нормальном каком-нибудь языке :-)
                    Ответить
                    • Чем же вам C++ не угодил? Какие-то конкретные замечания или так, лишь бы ляпнуть?
                      Ответить
                      • не буду повторять то, что уже красиво написано:
                        http://steps3d.narod.ru/tutorials/c-minus-minus.html
                        Ответить
                        • То решение (MFC), которые было предожено, выглядело явным уродством и не зря его в шутку называли Micro$oft Frustration Classes. То, что получалось уже не было нормальным текстом на С++, а представляло из себя уродливое нагромождение непонятных макросов.

                          Со временем пришло понимание, что на С++ иначе просто нельзя !!! Средства, изначально заложенные в сам язык, настолько негибки и жестки, что реализовывать системы, требующие гибкости на С++ было крайне тяжело и постояннно приводило к кривым способам (т.е. это бага а фича :)).

                          Ну что можно сказать, дальше можно уже не читать, а автору сего высера советую взглянуть на Qt и удавится
                          Ответить
                          • > а автору сего высера советую взглянуть на Qt и удавится

                            Увидеть Париж и умереть :-)

                            Пора бы вспомнить, что Qt - это как раз НЕ C++, это надстройка над C++. А точнее это отчаянная попытка преодолеть отсутствие в нём элементарных средств вроде делегирования.
                            Ответить
                            • Помоему хорошая библиотека, а раз её написали, то уже есть достаточно возможностей в языке.
                              Ответить
                            • Ну не такая уж прямо и отчаянная, а вполне себе успешная. А то что автор не видел ничего, кроме MFC и делает на его основе такие далеко идущие выводы мало о чем говорит.
                              Ответить
                            • MFC is not a C++ - it's a stupid library
                              Ответить
                            • а можно пример делегирования который невозможен на С++...
                              Ответить
                        • Smalltalk, Python... Может быть. Для некоторых решений. Автор упирает на жесткость С++ как недостаток - для меня же это основной мотив его использования. На чем вы будете писать встроенные приложения? На C или на асемблере, когда под рукой объектно ориентированный язык? Это почти как копать котлован лопатой, потому что экскаватор сложен в обращении. :-)
                          Не нравится автору STL - так никто не неволит, используйте сторонние библиотеки. Loki и Boost - произведения искусства, почему не сосредоточится на них в рассмотрении?
                          Про ссылки вообще смешно - если синтаксис языка говорит о том, что нужно использовать "&" для передачи параметра по ссылке, а мы об этом забыли... Это говорит о большой харизме.. ой, простите, маразме :-)
                          То же относится к проблемам старых компиляторов. Мы что, историю изучаем, или выбираем инструмент решения задачи?
                          Да, C++ не лишен недостатков, и граблей в нем огромное количество, и для изучения он не прост. Для определенного круга задач, однако, он остается оптимальным инструментом. При следовании набору правил, на C++ пишутся программы, поведение которых жестко детерминировано. Например, я точно знаю, когда создается объект, когда его копия, когда он уничтожается и даже откуда берется память для его размещения. При этом бо`льшую часть ошибок, действительно проверяет компилятор еще до запуска программы.
                          Ответить
                          • Ну забытое & (разименование) в параметре функции это в какой-то степени проблема. Должно быть что-то вроде IN, OUT, INOUT. Тоесть в синтаксисе языка должен кодироваться не низкоуровневый механизм, каким образом передавать параметр, а то для чего нам нужен обьект и как мы его будем использовать, а там уж компилятор это будет решать, каким образом что передовать и с привлечением каких механизмов. В С++ это поручаеться человеку, но человек может и ошибиться, а потом очень долго искать причину ошибки с отладчиком.
                            Ответить
                            • & - это не проблема, это совершенно самостоятельный спецификатор типа данных. Довольно удобный, если знать как его использовать (вспоминаем аналогию с экскаватором). Точно так, как передаем параметры в функцию, можно определять переменные. Конечно, ключевое слово, например reference, меня бы порадовало больше, но вспомните, когда создавался стандарт. Венгерская конвенция именования, которая используется в STL меня тоже не радует.
                              Если не знаем как пользоваться спецификатором &, вероятно, лучше почитать умных книжек, прежде чем садиться писать программы.
                              Ответить
                        • Дядьку со steps3d лучше слушать только за графику. В этом он шарит. За языки и платформы он слишком религиозен и не в теме. Почитайте его последние высказывания про java и с#.
                          Ответить
                          • Вы знаете этого "дядьку"?
                            Интересно, а в каком языке он достиг наивысшего дао?
                            Или для его задач пока не придуман хороший язык высокого уровня, и "дядька" занимается его созданием?
                            Ответить
                            • Лично его не знаю. Но знаю чем он занимается и читал большенство его статей. Про графику пишет очень хорошо: доступно, с примерами. Про его религиозность: вы почитайте его блог на том же сайте, его высказывания про MS, C++, Java и C# всё станет ясно. Он слишком категоричен в своих высказываниях.
                              Ответить
                    • Я хотел было написать: "Не будем флеймить, мы же вполне разумные люди".
                      К сожалению я опоздал...
                      Тут уже много написано. Что-то по делу, что не по делу...
                      Главная мысль, которую следует усвоить: каждая сущность создана для чего-то, и у каждой сущности есть своё место. Так вот C++ по скорости разработки и эффективности в определённых задачах не сравним с другими языками. Он универсален, и его можно применять и на космической станции и для подсчёта носков в магазине. Но для решения каждой конкретной задачи могут существовать свои средства. Зачем вам C++ , если вы не считаетесь с машинными средствами? Зачем вам С++, если вас не волнует расширяемость и гибкость системы? Зачем вам С++? Какую задачу вы хотите решать? В каких вы находитесь временных рамках? Какими вы располагаете ресурсами? Аккуратно проанализировав ситуацию, вы придёт к заключению о том, на каком именно языке вы будете что-то реализовывать. Это может быть и машинный язык, и MSIL, и fortran, и C, и С++, и Java, и Python, и LISP, и Neko или Javascrpit, Perl или PHP, и ещё огромный спектр языков...
                      Фанатизм пока что помогал людям только в борьбе между собой за территорию. Кроме "корытных" проблем, бывают ещё и "звёздные" задачи.
                      Ответить
          • for (int s=0;s<size;s++, first[s]='0');
            Ответить
    • for (int s=0;s<size;s++) {
         first[s]='0';
      }


      можно еще так)
      for (int s=0;(s<size)&&(first[s]='0');s++);
      Ответить
      • По-моему, можно и так
        memset(first,'0',sizeof(first));
        Ответить
        • Одна из вещей за которые надо расстреливать - memset в объектно ориентированных языках. Примерно месяц жизни в общей сложности ушел у меня на борьбу с последствиями memset'а. Никогда, слышите, никогда не пользуйтесь memset, memcpy для любых данных отличных от блока неструктурированной памяти.
          Ответить
        • memset прекрасно убивает таблицу виртуальных функций обьекта.
          Ответить
        • Ты точно уверен, что sizeof(first) вернёт размер массива?
          Ответить
          • я уверен, для массивов всегда так делаю... а кто использует memset для очистки классов с виртуальными функциями - тот дурак...
            Ответить
            • Даже если у класса нет виртуальных функций после memset'a возможны проблемы. Сталкивался. Но Вы можете его использовать :-). Ничто не убеждает так, как большая шишка на лбу от граблей.
              Ответить
              • если это POD класс, но проблемы невозможны... в остальных случаях программист идиот...
                Ответить
                • *то проблемы невозможны*
                  Ответить
                • а если в классе перегружены операторы new и delete он все еще POD? ;-)
                  Ответить
                  • по моему да, так как эти операторы являются статическими по умолчанию... но я не проверял...
                    Ответить
                    • Гы. То есть,
                      > если это POD класс, но проблемы невозможны... в остальных случаях программист идиот...
                      но отличить POD от не POD не всегда получается сразу :-)
                      Могу с уверенностью сказать: в компиляторе C++ VS6 объекты с перегруженными new и delete ведут себя нестабильно после memset'a: вместо перегруженного для класса вызывается глобальный delete, со всеми вытекающими.
                      Ответить
                      • для POD класса есть определение в стандарте, я думаю что не нужно иметь много моска чтоб выполнить 4 приведенных там условия...
                        а еще я думаю, что у комипилятора VS6 есть достаточно качественные новые версии, которые более соответствуют стандарту...
                        Ответить
            • Вроде, если передать массив в функцию, а внутри неё получить sizeof(массив), то можно получить проблемы, особенно если не верно передать таковой.
              Ответить
              • если в функцию передать массив в виде mas[] или *mas то естественно будут проблемы, а если mas[4] то скорее всего проблем не будет... я не проверял, так как ниразу не передавал массив в функцию кроме как по указателю...
                Ответить
            • А ещё может быть указатель на данные, то его можно использовать, как массив. В таких случаях sizeof вернёт размер указателя, а не массива.
              Ответить
              • в данном случае мы знаем что у нас first[8] (а могло быть first[CONST_SIZE])... остальные случаи наш моск вообще не сношают...
                Ответить
    • эээ... зачем столько споров?О_о
      проблема была в том что надо было size-1 в условии поставить. и присваивание внутри цикла.

      const int size=8;
      
      class Bin
      {
      public:
      	Bin();
      private:
      	char first[size];
      	char second[size];
      };
      
      Bin::Bin()
      {
      	for (int s=0;s<=size-1;s++)
                      first[s]='0';
      }
      Ответить
      • s<=size-1 equals s < size ?
        Ответить
      • He надо size-1, лучше
        for (int s=0;s<size;++s) {
        first[s]='0';
        }

        И почему мемсет не подойдёт? Дайте пруфлинков на возможные проблемы. Ведь если не заходить за границы массива - ничего случиться не должно.
        Ответить
        • некоторые им чистят классы с виртуальными функциями и не умеют пользоваться оператором sizeof...
          Ответить
        • С точки зрения объектно ориентированного языка использование memset для любого типа данных кроме неструктурированной памяти - грязный хак. Вся "жесткость" языка, о которой шла речь выше, летит коту под хвост. Компилятор умывает руки и предлагает вам остаться с вашим страшным кодом наедине.
          Почитать эту занимательную историю более развернуто можно у Герба Саттера в задачах по C++.
          Ответить
          • это массив чаров фиксированного размера, сиречь - бинарные данные.
            о каких последствиях memset здесь может идти речь?
            развели дискуссию ни о чем. для разных задач - свои инструменты, и не надо религиозные вопросы поднимать по каждому поводу.
            Ответить

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