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

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    #include <stdio.h>
    
    int main() {
    	switch (3) {
    		for (int i = 3; i > 0; --i) {
    			case 3: printf("%d ololo?\n", i);
    		}
    	}
        return 0;
    }

    О сколько нам открытий чудных
    Готовит просвящения духх...


    Угодайте, что там: https://ideone.com/zbOzGZ

    Запостил: MasterJoda, 14 Сентября 2018

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

    • А в нашей голактике про это не рассказывали.
      Ответить
    • Ебать мой хуй
      Ответить
    • >Угодайте, что там
      UB?
      Ответить
    • Шланг, судя по всему не, проводит инициализации при входе в цикл - но при выходе из цикла кидает на начало.
      Ответить
      • > Шланг, судя по всему не, проводит инициализации при входе в цикл
        Не только шланг, ещё гцц и тцц, в цикл-то вошли не по-людски, а через жопу – сразу прыгнули внутру.

        > при выходе из цикла кидает на начало.
        Цикл цикличен :D первую проверку на входе-то пропустили.
        Ответить
        • Дык по стандарту так. Ты инициализацию перепрыгнул, вот она и не произошла. В переменной остался мусор.

          В c++ такой код не сконпелится, кстати.
          Ответить
          • Признайся честно: ведь было-то с парнем, а?.. Тиски-сосиски, ебля на полшишки, поцелуйчики после спермоглотка. Облегчи душу, публичным покаянием.
            Ну не верю я, что адепт-задрот, фанат онимея - и не пидр... Моя модель сознания отказывается это признавать.
            Ответить
            • Ну откуда у адепта-задрота и фаната анимья найдётся время на все эти ириски-записки? Подкорректируй свою модель сознания.
              Ответить
              • Ой, ты бедолага, тут девченки фанатки японских мультиков от безденежья на вебку в костюме кошкодевочек онанируюют, а ты с профессией и без бабы, ну найди ты себе какуюнить такую на сходке, будет тебе квартиру убирать, омлет рулетиками в офис складывать, будешь ее в Токио возить, костюмы покупать, каждую ночь сможешь то Аску, то Усаги или Ами, то еще какую принцессу Анджелиссу натягивать. Хватит мучится - кошкотелки, лисотелки, всякие девкоангелы ковайные есть суть суррогат. А настоящая девушка по своему интересна.
                Ответить
                • Только "по-своему".
                  Ответить
                  • Да, знаю что ошибаюсь - в школах Украины, когда я учился, русского был 1 час в неделю.
                    Ответить
                    • вместо дефиса нужно двоеточие с запятой.
                      Ответить
                    • Лол, ты на западенщине учился или в украинской школе?
                      Ответить
                      • На восточновщине, в школе с украинским языком преподавания.
                        Ответить
                        • И как ты туда попал?
                          Ответить
                          • В моем населенном пункте была одна школа.
                            Ответить
                            • Сочуствую. И как, пригодилась мова?
                              Ответить
                              • Да, документы читаю, с тест-тимом львовским общаюсь.
                                Ответить
                                • Их замечательно читают и и те, кто в русскоязычных школах учился. Или у вас и город был украиноязычным?
                                  Кто Путин?
                                  Ответить
                                  • Нет, суржеязым, Путин президент РФ исполняющий волю российского буржуазного класса.
                                    Ответить
                                    • А я думал хуйло.
                                      Ответить
                                    • Кстати, а где можно вживую услышать такой украинский, какой преподдают / каким говорчт по телеку?
                                      Ответить
                                      • На полтавщине или черниговщине - в остальных местах суржики.
                                        Ответить
                                        • Ещё на западенщине есть сверхебанутые говоры. Как железом по стеклу звучат.
                                          Ответить
                                          • За эбанутые говора вiдповiд держатi буде, мразiна. Цур тобi!
                                            Ответить
                    • А на мове оно как?
                      Ответить
                • > на сходке
                  Дык это на сходки ходить надо... Сложно.
                  Ответить
                  • Приходишь, а там школьники социобляди, попереебались все давно, а тут ты хикамори со своей котобуки цумуги.
                    Ответить
                  • Не боись, по морде там не бьют и про два стула не спросят (хотя ХЗ, может в Воркуте или Магадане есть и такие анимэшники :D), начни ходить - круг общения будет во всяком случае ближе чем где либо еще в реале. Кто не рискует - тот без пары сидит.
                    Ответить
                    • Да ты ж файка д++.
                      Ответить
                    • Ну подумаешь, спросят про два стула — ответит, что стульев с хуями не бывает, да и вообще они с мамой не настолько устали, чтобы садиться на какую-то хуйню, которую им предоставили жмоты.
                      Ответить
            • депт-задрот, фанат онимея девственник, но совершенно не обязательно пидр
              Ответить
    • http://risovach.ru/upload/2018/09/mem/patriarh_187360306_orig_.jpg
      Ответить
    • Пост говно, а автор, как вы уже могли догадаться - изрядный мудило.
      Ответить
    • 1. В сишке нет нормального свитча. Тот свитч, который есть в сишке, не является жёсткой рамочной конструкцией, в отличие от ифов и циклов. По сути это рамка (switch(условие){тело}) плюс тёплые ламповые старые недобрые метки, оставшиеся в наследство от спагетти-кода, да простят меня пастафариане. Потому и метки эти можно лепить где угодно, и выполнение веток по умолчанию «проваливается», поэтому нужно лепить нелогичный break.

      2. В сишке for — это синоним для while, только зачем-то заняли ещё два места (в других ЯП есть циклы с другим способом задания границ диапазона перечисления и с однократным вычислением этих границ, а тут по сути макрос).

      Итак, сначала избавимся от for:
      #include <stdio.h>
      
      int main() {
      	switch (3) {
                      int i = 3;
      		while (i > 0) {
      			case 3: printf("%d ololo?\n", i);
                              --i;
      		}
      	}
          return 0;
      }
      Ответить
      • Дальше будет труднее. case 3: — это всего лишь метка, а не часть структуры кода (в отличие от Паскаля, например). На той строчке, где switch, генерируется таблица переходов (реализация может зависеть от конкретного компилятора и от флагов оптимизации). Чтобы не забивать голову таблицей, напишу эквивалент через if:
        #include <stdio.h>
        
        int main() {
                if (3 == 3) goto label3; // так разворачивается пара switch(3) при наличии case 3:
                // в следующих строчках могли бы быть ваши рекламы ещё сравнения и переходы
                        int i = 3;
        		while (i > 0) {
        			label3: printf("%d ololo?\n", i);
                                --i;
        		}
        
            return 0;
        }
        Ответить
        • Однако, хитро сделанный компилятор может считать, что программист в здравом уме и в трезвой памяти не будет перемешивать свитч с фором (потому что это UB), поэтому наоптимизирует так, что код будет работать неправильно.
          Ответить
      • Фу! Как ниструктурна!
        Тьфцу!
        Ответить
    • Почему это говно вообще компилируется?
      Ответить
      • Я уже написал: потому что case в сишке — это не элемент конструкции (как, например, else в условном операторе), а тупо метка (но только специальная метка, которую компилятор помещает в таблицу переходов), а метку можно воткнуть куда угодно.

        Вот от такого старого говна до сих пор не могут избавиться.
        Ответить
    • То ли дело BASIC:
      10 DIM A(1)
      20 A(1) = 50
      30 GOTO A(1)
      40 FOR I = 3 TO 1 STEP -1
      50 PRINT I, "OLOLO?"
      60 NEXT I
      70 END


      https://tio.run/##[email protected]@VpAxNMSNmYYuVtTz/mOgsTp3zHPt9nc4JRqcmtKGIKOXPqFEwZYzBWPOfnNGbBcqvDD4KrFbOSAQVjHlR2kLFCMzoaQIqGVpuvlHFkLpz7gU
      Ответить
      • Забавно. Интерпретатор увидел инструкцию NEXT, а FOR не увидел. Значит, UBASIC — это ещё не структурный BASIC, а настоящий построчный интерпретатор.
        Ответить
        • Идея для других ЯП: реализовать функции _for(counter, startValue, endValue, step) и next(counter), которые создают цикл. Мы можем сохранять в собственном стеке адреса для перехода. Самым сложным будет реализовать отмену тела цикла, если изначально нарушены условия (например, endValue<startValue при положительном step), потому что next ещё не вызывался и ничего не сохранял.
          Ответить
          • Я теперь понял, почему в неструктурированном Фортране-66 у оператора DO нужно было указывать метку конца цикла: так они облегчили жизнь компилятору в случае, если предусловие сразу не выполняется.
            Ответить
          • Наговнокодил (осторожно, зависит от calling convention и не будет работать без stack frame):
            #include <stdio.h>
            typedef struct {
              int endValue;
              void * startBody;
            } loop_record;
            
            loop_record stack[1000];
            int head = 0;
            
            void push(loop_record value) {
                stack[head] = value;
                head++;
            }
            
            loop_record pop() {
                head--;
                if (head < 0) exit(255);
                return stack[head];
            }
            
            void _do(void * label, int * counter, int from, int to) {
              void ** frame = __builtin_frame_address(0);
              *counter = from;
            
              if (*counter > to) {
                frame[1] = label;  // Эквивалент goto *label
                return;
              }
            
              loop_record current;
              current.endValue = to;
              current.startBody = frame[1];
              push(current);
            }
            
            void _next(int * counter) {
              void ** frame = __builtin_frame_address(0);
              (*counter)++;
            
              loop_record current = pop();
              if (*counter <= current.endValue) {
                push(current);
                frame[1] = current.startBody; // Эквивалент goto *startBody (на след. инструкцию после вызова _do)
              }
            }
            
            int main() {
              int i;
              _do(&&end,&i, 1, 5);
                printf("Хорошо живёт на свете Винни-пух (%d).\n", i);
              _next(&i);
              end:
                printf("Оттого поёт он эти песни вслух.\n");
            }
            Ответить
            • Если не проверять предусловие, то можно обойтись и без метки:
              #include <stdio.h>
              typedef struct {
                int endValue;
                void * startBody;
              } loop_record;
              
              loop_record stack[1000];
              int head = 0;
              
              void push(loop_record value) {
                  stack[head] = value;
                  head++;
              }
              
              loop_record pop() {
                  head--;
                  if (head < 0) exit(255);
                  return stack[head];
              }
              
              void _for(int * counter, int from, int to) {
                void ** frame = __builtin_frame_address(0);
                *counter = from;
              
                loop_record current;
                current.endValue = to;
                current.startBody = frame[1];
                push(current);
              }
              
              void _next(int * counter) {
                void ** frame = __builtin_frame_address(0);
                (*counter)++;
              
                loop_record current = pop();
                if (*counter <= current.endValue) {
                  push(current);
                  frame[1] = current.startBody; // Эквивалент goto *startBody (на след. инструкцию после вызова _do)
                }
              }
              
              int main() {
                int i;
                _for(&i, 1, 5);
                  printf("Хорошо живёт на свете Винни-пух (%d).\n", i);
                _next(&i);
                printf("Оттого поёт он эти песни вслух.\n");
              }
              Ответить
              • Можно сократить функцию _for, потому что в ней нам фрейм не нужен:
                void _for(int * counter, int from, int to) {
                  *counter = from;
                
                  loop_record current;
                  current.endValue = to;
                  current.startBody = __builtin_return_address(0);
                  push(current);
                }
                Ответить
                • Попробовал применить setjmp, всё равно приходится фиксить адрес возврата:
                  #include <stdio.h>
                  #include <setjmp.h>
                  #include <string.h>
                  typedef struct {
                    int endValue;
                    void * startBody;
                    jmp_buf environ;
                  } loop_record;
                  
                  loop_record stack[1000];
                  int head = 0;
                  
                  void push(loop_record value) {
                      stack[head] = value;
                      head++;
                  }
                  
                  loop_record pop() {
                      head--;
                      if (head < 0) exit(255);
                      return stack[head];
                  }
                  
                  void _for(int * counter, int from, int to) {
                    *counter = from;
                    loop_record current;
                    current.startBody = __builtin_return_address(0);
                    current.endValue = to;
                  
                    jmp_buf env;
                    int jmpval = setjmp(env);
                  
                    if (jmpval > 0) {
                      void ** frame = __builtin_frame_address(0);
                      current = pop();
                      frame[1] = current.startBody; // иначе перейдём не на тело цикла, а к концу
                    } else {
                      memmove(current.environ, env, sizeof(env));
                    }
                    push(current);
                  }
                  
                  void _next(int * counter) {
                    (*counter)++;
                  
                    loop_record current = pop();
                    if (*counter <= current.endValue) {
                      push(current);
                      longjmp(current.environ, 1);
                    }
                  }
                  
                  int main() {
                    int i;
                    _for(&i, 1, 5);
                      printf("Хорошо живёт на свете Винни-пух (%d).\n", i);
                    _next(&i);
                    printf("Оттого поёт он эти песни вслух.\n");
                  }
                  Ответить
                  • Слепил аналог сишного свитча (к сожалению, реализация тоже полагается на calling conventions):
                    #include <stdio.h>
                    #include <setjmp.h>
                    #include <string.h>
                    typedef struct {
                      jmp_buf environ;
                    } loop_record;
                    
                    loop_record stack[1000];
                    int head = 0;
                    
                    void push(loop_record value) {
                        stack[head] = value;
                        head++;
                    }
                    
                    loop_record pop() {
                        head--;
                        if (head < 0) exit(255);
                        return stack[head];
                    }
                    
                    void _switch(int counter, void ** labels) {
                      jmp_buf env;
                      int jmpval = setjmp(env);
                    
                      if (jmpval == 0) {
                        loop_record current;
                        memmove(current.environ, env, sizeof(env));
                        push(current);
                        void ** frame = __builtin_frame_address(0);
                        frame[1] = labels[counter];
                      } else {
                        void ** frame = __builtin_frame_address(0);
                        frame[1] = labels[0]; // выходим
                      }
                    }
                    
                    void _break() {
                      loop_record current = pop();
                      longjmp(current.environ, 1);
                    }
                    
                    int main() {
                      void * jmpTable[] = {&&end, &&case_1, &&case_2, &&case_3};
                      _switch(2, jmpTable);
                        case_1:
                        printf("Первый багор.\n");
                        _break();
                        case_2:
                        printf("Второй багор.\n");
                        _break();
                        case_3:
                        printf("Третий багор.\n");
                        _break();
                      end:
                      printf("Всё!.\n");
                    }
                    Ответить
                    • А зачем мне setjmp? Можно же сделать короче:
                      #include <stdio.h>
                      typedef struct {
                        void * ret;
                      } loop_record;
                      
                      loop_record stack[1000];
                      int head = 0;
                      
                      void push(loop_record value) {
                          stack[head] = value;
                          head++;
                      }
                      
                      loop_record pop() {
                          head--;
                          if (head < 0) exit(255);
                          return stack[head];
                      }
                      
                      void _switch(int counter, void ** labels) {
                          loop_record current;
                          current.ret = labels[0];
                          push(current);
                          void ** frame = __builtin_frame_address(0);
                          frame[1] = labels[counter];
                      }
                      
                      void _break() {
                          loop_record current = pop();
                          void ** frame = __builtin_frame_address(0);
                          frame[1] = current.ret;
                      }
                      
                      int main() {
                        void * jmpTable[] = {&&end, &&case_1, &&case_2, &&case_3};
                        _switch(2, jmpTable);
                          case_1:
                          printf("Первый багор.\n");
                          _break();
                          case_2:
                          printf("Второй багор.\n");
                          _break();
                          case_3:
                          printf("Третий багор.\n");
                          _break();
                        end:
                        printf("Всё!.\n");
                      }
                      Ответить
      • Проверяем разные реализации.
        Quick BASIC переходить на метку, указанную переменной, не умеет.
        Следующая программа приводит к бесконечному циклу (печатает 0):
        30 GOTO 50
        40 FOR I = 3 TO 1 STEP -1
        50 PRINT I, "OLOLO?"
        60 NEXT I
        70 END
        Ответить
        • Power BASIC ведёт себя аналогично.
          Ответить
          • Free BASIC (fbc) соглашается компилировать эту программу только в режиме совместимости. В режиме совместимости он не понимает GOTO на переменный адрес (как и QBASIC); после правки программа один раз выводит ноль и завершается (ну хоть не зацикливается, и то хорошо).
            Ответить
          • Вспомнил деццтво, поставил себе емулятор j2me и поставил mobile basic:
            10 DIM A%(1)
            20 A%(0)=50
            30 GOTO A%(0)
            40 FOR I%=3 TO 1 STEP -1
            50 PRINT STR$(I%)+" OLOLO?"
            60 NEXT I%
            70 END
            Error: NEXT before FOR at line 60. :(
            Ответить
            • Запустил эмулятор Commodore C64. Он отказался принимать GOTO на переменный адрес. С GOTO 50 вывел:
              0 OLOLO?
              
              ?NEXT WITHOUT FOR ERROR IN 60
              Ответить
      • Кстати, UBASIC ты видел только на tio.run или где-то ещё? До пакета ubmalm.zip добрался?
        Ответить
        • > UBASIC ты видел только на tio.run
          Да, я там часто хуйнёй страдаю, ещё на compileonline :)

          > ubmalm.zip
          Нихрена не понял, причём здесь какой-то матан на uBASIC?
          Ответить
    • А в Forth goto нет :(
      Ответить
    • Лол:
      // https://ru.wikipedia.org/wiki/Устройство_Даффа
      
      #define DECLARE() int state
      
      #define INIT() state = 0
      
      #define BEGIN switch (state) { \
                            case 0:
      
      #define YIELD(val) do { \
                              state = __LINE__;   \
                              return val;         \
                            case __LINE__:        \
                              ;                   \
                            } while (0)
      
      #define END }
      
      #include <iostream>
      using namespace std;
      
      class machine {
          DECLARE();
      public:
          machine()
          {
              INIT();
          }
      
          const char* next()
          {
              BEGIN;
                  YIELD("мама");
                  YIELD("мыла");
                  YIELD("раму");
              END;
              return NULL;
          }
      };
      
      int main()
      {
          machine m;
          while (const char* val = m.next()) {
              cout << val << ' ';
          }
          return 0;
      }
      Ответить
      • Прикольно:
        #define DECLARE() int state
        
        #define INIT() state = 0
        
        #define BEGIN switch (state) { \
                              case 0:
        
        #define YIELD(val) do { \
                                state = __LINE__;   \
                                return val;         \
                              case __LINE__:        \
                                ;                   \
                              } while (0)
        
        #define END }
        
        #include <iostream>
        using namespace std;
        
        class fibs {
            DECLARE();
            int n, a = 0, b = 1, k = 0;
        public:
            fibs(int x)
            {
                INIT();
                n = x;
            }
        
            int next()
            {
                int t;
                BEGIN;
                    while (++k <= n) {
                        t = a + b;
                        a = b;
                        b = t;
                        YIELD(a);
                    }
                    
                END;
                return 0;
            }
        };
        
        int main()
        {
            fibs f(10);
            while (int val = f.next()) {
                cout << val << ' ';
            }
            return 0;
        }
        Ответить
        • Как сделать корутинку из говна, палочек, препроцессора и странного синтаксиса си?
          Ответить
          • В асио это на полном серьезе предлагается к использованию https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/overview/core/coroutine.html
            Ответить
            • В чем цимес?
              В лёгкой реализации consumer/producer?
              Ответить
              • В том, чтобы не писать лапшу из колбеков в асинхронном коде.
                Ответить
          • Зачем делать, есть уже готовая библиотека protothreads. Там точно также Дафф девайс обмазан макроговном.
            Ответить
    • Изыди просвящения духх... Из ануса!
      Ответить
    • На "PHP" не переводится: "PHP" требует case сразу за switch.
      Ответить

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