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

    +142

    1. 1
    2. 2
    3. 3
    4. 4
    do
      { 
    ...
      } while ((strcmp(input,"") != 0)); /* till end of string */

    нашел в прошивке одного очень известного производителя сетевого оборудования, они так парсят команды, введенные пользователем

    Запостил: ivanria, 21 Мая 2015

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

    • Ну подумаешь, боятся лезть по указателю напрямую...
      Ответить
      • хм, если стоит оптимизация, компилятор никогда не вызывет strcmp
        Ответить
        • Никогда не говори никогда. Всё зависит от компилятора и его настроения.

          Но в этом случае, наверное, и правда оптимизнётся в while (*input)
          Ответить
          • > зависит от компилятора и его настроения.
            а настроение зависит от того как настроишь
            Ответить
        • Можно идиотский вопрос, а почему он никогда её не дёрнет?
          Ответить
          • Потому что он оптимизнёт этот код до while (*input), в котором вызова strcmp уже не будет.
            Ответить
          • сравнит с нулем разыменованный указатель, что и требовалось от функции strcmp, почему так, это уже в исходник компилятора
            Ответить
    • Нормальный код, я считаю. Ибо абстрагируется от сишкоблядской реализации строк.
      Ответить
      • ни от чего он не абстрагируется, он просто делает ненужный вызов, что еще за реализация строк? в си есть массивы и указатели (массивы по сути синтаксис над указателями), кто этого не понял, то пишет такое блядство, хорошо, что в компиляторах есть защита от такого кода
        Ответить
        • А если в будущем строки станут не говнищем-оканчивающимся-на-ноль, а нормальным классом, и тогда все литералы и все функции тоже поменяются на нормальные. И тогда этот код не надо будет менять. То, что компилятор умеет оптимизировать - да, это хорошо.
          Про ненужные вызовы я не понял - тут что, проблема с преферансом? Это сравнение делается при отрисовке экрана в каждом пикселе?
          Ответить
          • >А если в будущем строки станут не говнищем-оканчивающимся-на-ноль

            если так не нравятся строки, то запили собственный класс с конструктором и методами и сиди вызывай методы в каждом цикле, где достаточно просто написать for(; *input; input++)
            Ответить
            • > запили собственный класс

              В крестах я так и делаю. Тут кстати нормальный код.

              > просто написать for(; *input; input++)

              Что это за говнокод? Указатели какие-то ещё...
              Ответить
              • идите си учить
                Ответить
                • Зачем, я и так знаю основы. Просто не вижу смысла загромождать код низкоуровневыми подробностями.
                  Ответить
                  • си низкоуровневый язык, делайте классы в си (если надо) или используйте си++
                    Ответить
                    • > классы в си
                      Толстовато, конечно... Откуда у тебя в сишке классы? Но пародию на ООП на сишке таки можно замутить.
                      Ответить
                      • нормальные классы, я вообще-то плюсы не изучал, в си я делаю структуру, которая имеет указатели на void, enum type, и указатель на массив функций, получается класс и даже полиморфизм :)
                        Ответить
                        • Писать больно уж дохуя, когда такие классы объявляешь.
                          Ответить
                          • Заведи макросы. Хотя нет. Код надо генеритъ на пхп
                            Ответить
                            • Макросыыыы...
                              #define BEGIN {
                              #define VAR(x) {x; add_to_stack_vars_list(&x);}
                              #define END free_stack_vars(); }
                              #define RETURN(x) {free_stack_vars(); return x;}
                              Ответить
                              • Кстати, а такая хрень же реально должна помочь, не?
                                Ответить
                                • для начала, не голые {} в макросах, а с do while(0)
                                  ну и, наконец, что распидорасит, если сделать внутренний begin end во внешнем begin end?
                                  Ответить
                                  • это мелочи реализации
                                    в BEGIN добавь создание нового списка локальных переменных, в END уничтожение этого списка
                                    Ответить
                          • бешеной собаке килОметр - не крюк
                            Ответить
                            • И не то слово. Они и на хаскеле готовы писать.
                              Ответить
                              • На хаскеле имплементировал тайпкласс и все.
                                Ответить
                      • libcello очень неплохо выглядит, кстати.
                        Ответить
                      • ну не такая уж и пародия. Вон ядро линупса хоть и написанно на си, но вполне себе обьектно-ориенторованое.
                        Ответить
                        • Ядро пинуса такое же объектно ориентированное, как и выньопий.
                          Ответить
                          • так а в чём проблема? Абстрагирование, инкапсуляция, полиморфизм - всё есть. Как минимум драйвера ООПешные насквозь.
                            Ответить
                      • >Откуда у тебя в сишке классы?

                        Из 80-го года.
                        Ответить
                        • я вот даже ассемблер видел с ооп. но вот сишку реально не доработали. надо было разрешить наследовать структуры.
                          Ответить
                    • Это не повод обмазываться низкоуровневым дерьмом там, где этого не нужно.
                      Ответить
                      • Если тебе не хочется обмазываться низкоуровневым дерьмом, то зачем ты вообще выбрал си, а не какой-нибудь язык высокого уровня?
                        Ответить
                        • не хочу обмазываться жабьим дерьмом с гц и исключениями
                          сишка даёт возможность на лезть в дерьмо, а жаба не даёт
                          Ответить
                          • Ты из тех, кто считает, что исключения не нужны?
                            Ответить
                          • Rust уже вышел. Нет ни гц, ни исключений.
                            Ответить
                            • а есть вообще что? а если найду?
                              Ответить
                              • Featuring

                                zero-cost abstractions
                                move semantics
                                guaranteed memory safety
                                threads without data races
                                trait-based generics
                                pattern matching
                                type inference
                                minimal runtime
                                efficient C bindings
                                Ответить
                                • zero-cost abstractions
                                  не возможно
                                  Ответить
                                  • http://tinyurl.com/qcvbab9
                                    Ответить
                                    • Вообщем это означает, что иногда можно дешевле. Ясно
                                      Ответить
                                      • uint64_t hash_short(const char *s, size_t length,
                                         uint64_t seed) {
                                          if (length >= 4 && length <= 8)
                                            return hash_4to8_bytes(s, length, seed);
                                          if (length > 8 && length <= 16)
                                            return hash_9to16_bytes(s, length, seed);
                                          if (length > 16 && length <= 32)
                                            return hash_17to32_bytes(s, length, seed);
                                          if (length > 32)
                                            return hash_33to64_bytes(s, length, seed);
                                          if (length != 0)
                                            return hash_1to3_bytes(s, length, seed);
                                          return k2 ^ seed;
                                        }

                                        ну охуеть теперь
                                        Ответить
                      • Я тебя не узнаю. Ты же сам ратовал за структуры с указателями на функции
                        Ответить
                        • А виртуальщину я не предлагаю.
                          Кстати там, где мне был нужен динамический полиморфизм, мне всё равно виртуальные методы не пригодились. Потому что мне нужны были не только виртуальные методы, но и виртуальные статические константы. Пришлось руками заполнять поля метаклассов.
                          Ответить
                      • > Это не повод обмазываться низкоуровневым дерьмом там, где этого не нужно.
                        struct MyStream
                        {
                          std::function<void(char)> PutChar;
                          std::function<char()> GetChar;
                        }
                        Ответить
                      • у каждого средства есть свое назначение, в ядре линукс ооп реализовано на чистом си, в шиндовс на плюсах
                        Ответить
                  • >>идите си учить
                    >Зачем, я и так знаю основы.
                    Ты лучше не препирайся, а послушай девушку. Дело ведь говорит
                    Ответить
                    • Выслушай женщину - и сделай наоборот.
                      p.s. въебал минус за то, что бросаешь тень на мораль холостяцкой жизни. главное - разными руками дрочить, а то член станет напоминать джойстик.
                      Ответить
              • В сишке тоже можно свою либу замутить. Работать потом на порядок удобнее, чем с этим null-terminated говном. Как-то так:
                string a = str_from_pchar("hui");
                string b = str_from_buf("pizda", 5);
                string buf = str_alloc(0);
                str_append(buf, a);
                str_append_pchar(buf, ", ");
                str_append(buf, b);
                str_append_buf("i Djihurda", 11);
                printf("%s\n", str_get_buf());
                str_free(a);
                str_free(b);
                str_free(buf);
                Ответить
                • Заведи структуру с массивом и длинной и ебись конем эти аллокации.конструктор копирования и оператор сравнения из коробки
                  Ответить
                  • struct {
                    char buf[BUF_LENGTH];
                    int length;
                    }; Так что ли?

                    Как этот BUF_LENGTH выбрать? Что делать, если надо сохранить более длинннную строку?
                    Ответить
                    • > Как эту длину выбрать?
                      Длина доступного в говносистеме пути помноженная на 2, например.

                      > Что делать, если строка длиннее?
                      Кричать "ах я лох, но почему же я не подобрал правильную длину строки для данного приложения" и скорее отправлять на мой фаллический счет на кайманах 300 грамм золота.
                      Ответить
                    • нет size_t length
                      Ответить
                    • с точностью до наоборот
                      struct string {
                      size_t len;
                      size_t maxlen;
                      char[1] data
                      } ;

                      а выделять так: malloc(sizeof(string) + real_size - 1);

                      Если надо более длинную строку - реаллок в зубы и вперед.
                      Ответить
                      • В общем-то string у меня примерно так и был реализован. Только с char[0], да простят меня компиляторы.

                        Но laMer007 явно не это имел в виду. Тут же выделять и освобождать придётся.
                        Ответить
                        • Ну выделять да, придется. Но можно не освобождать! Памяти же много в компьютере. А всё лишнее в своп ляжет. Или использовать alloca и молиться что бы хватило стека.
                          Ответить
                          • тру парни делают реализацию строк с встроенной перемещающей сборкой мусора. делается проще простого и выделения за о 1
                            Ответить
                    • > Что делать, если надо сохранить более длинннную строку?

                      Веревки (или Б-дерево) которые можно реализовать и на Си, т.как не нужно заранее знать размер строк, а можно выделять по мере необходимости, и реаллоков не будет с добавлением всего-лишь логарифмического фактора. При чем, возможен даже выигрыш при интенсивном копировании / конкатенации и т.п.
                      Ответить
          • > А если в будущем строки станут <...> нормальным классом
            > И тогда этот код не надо будет менять.
            Как удобно! В мире останется 4 неизменных строки, которые не полагались на \0.
            Правда, остальные миллиарды строк всё же придётся переписать.
            Ответить
      • Так strcmp только сишные строки и умеет. Вот если бы там был шаблон...
        Ответить
        • Этот код позволяет сравнивать строку с пустой, не зная устройства строк. И похер, что там стрцмп только умеет.
          Ответить
          • Мне кажется, там внутри обязательно есть (++input), поэтому ещё итераторы понадобятся.
            Ответить
            • http://ideone.com/0NPv8o

              #include <string>
              #include <iostream>
              #include <vector>
              
              // Should go first, so the overload-specialize mess will work 
              template <typename C>
              bool is_empty_string(const C* str) {
                  return *str == '\0';
              }
              
              template <typename T>
              bool is_empty_string(T&& str) {
                  // For vectors, strings, etc.
                  return str.empty();
              }
              
              int main() {
                  std::boolalpha(std::cout);
                  
                  std::vector<char> ve;
                  std::vector<char> vne = {'C', '+', '+'};
                  const char* ce = "";
                  const char* cne = "C++";
                  std::string se = "";
                  std::string sne = "C++";
                  
                  std::cout << is_empty_string(ve)  << " "
                            << is_empty_string(vne) << " "
                            << is_empty_string(ce)  << " "
                            << is_empty_string(cne) << " "
                            << is_empty_string("")  << " "
                            << is_empty_string("C++") << " "
                            << is_empty_string(se)  << " "
                            << is_empty_string(sne) << std::endl;
              }
              Ответить
              • std::cout << is_empty_string(nullptr);
                Ответить
                • Вот меня кто-то плюсанул, а ведь я почти уверен, что не скомпилируется, ибо выберется другая перегрузка. шаблонная, а не пчар
                  Ответить
    • Известного чем? Не длинк ли?
      Ответить
    • Все равно не понял, что не так?
      Ответить

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