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

0

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

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

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

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

        В c++ такой код не сконпелится, кстати.
        Ответить
        • Признайся честно: ведь было-то с парнем, а?.. Тиски-сосиски, ебля на полшишки, поцелуйчики после спермоглотка. Облегчи душу, публичным покаянием.
          Ну не верю я, что адепт-задрот, фанат онимея - и не пидр... Моя модель сознания отказывается это признавать.
          Ответить
          • Ну откуда у адепта-задрота и фаната анимья найдётся время на все эти ириски-записки? Подкорректируй свою модель сознания.
            Ответить
            • Ой, ты бедолага, тут девченки фанатки японских мультиков от безденежья на вебку в костюме кошкодевочек онанируюют, а ты с профессией и без бабы, ну найди ты себе какуюнить такую на сходке, будет тебе квартиру убирать, омлет рулетиками в офис складывать, будешь ее в Токио возить, костюмы покупать, каждую ночь сможешь то Аску, то Усаги или Ами, то еще какую принцессу Анджелиссу натягивать. Хватит мучится - кошкотелки, лисотелки, всякие девкоангелы ковайные есть суть суррогат. А настоящая девушка по своему интересна.
              Ответить
                • Да, знаю что ошибаюсь - в школах Украины, когда я учился, русского был 1 час в неделю.
                  Ответить
                  • Лол, ты на западенщине учился или в украинской школе?
                    Ответить
                    • На восточновщине, в школе с украинским языком преподавания.
                      Ответить
                          • Сочуствую. И как, пригодилась мова?
                            Ответить
                            • Да, документы читаю, с тест-тимом львовским общаюсь.
                              Ответить
                              • Их замечательно читают и и те, кто в русскоязычных школах учился. Или у вас и город был украиноязычным?
                                Кто Путин?
                                Ответить
                                • Нет, суржеязым, Путин президент РФ исполняющий волю российского буржуазного класса.
                                  Ответить
                                  • Кстати, а где можно вживую услышать такой украинский, какой преподдают / каким говорчт по телеку?
                                    Ответить
                                    • На полтавщине или черниговщине - в остальных местах суржики.
                                      Ответить
                                      • Ещё на западенщине есть сверхебанутые говоры. Как железом по стеклу звучат.
                                        Ответить
                                        • За эбанутые говора вiдповiд держатi буде, мразiна. Цур тобi!
                                          Ответить
                • Приходишь, а там школьники социобляди, попереебались все давно, а тут ты хикамори со своей котобуки цумуги.
                  Ответить
                • Не боись, по морде там не бьют и про два стула не спросят (хотя ХЗ, может в Воркуте или Магадане есть и такие анимэшники :D), начни ходить - круг общения будет во всяком случае ближе чем где либо еще в реале. Кто не рискует - тот без пары сидит.
                  Ответить
                  • Ну подумаешь, спросят про два стула — ответит, что стульев с хуями не бывает, да и вообще они с мамой не настолько устали, чтобы садиться на какую-то хуйню, которую им предоставили жмоты.
                    Ответить
          • депт-задрот, фанат онимея девственник, но совершенно не обязательно пидр
            Ответить
  • Пост говно, а автор, как вы уже могли догадаться - изрядный мудило.
    Ответить
  • 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 в условном операторе), а тупо метка (но только специальная метка, которую компилятор помещает в таблицу переходов), а метку можно воткнуть куда угодно.

      Вот от такого старого говна до сих пор не могут избавиться.
      Ответить
    • Забавно. Интерпретатор увидел инструкцию 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
      Ответить
        • 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?
        Ответить
  • Лол:
    // 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;
      }
      Ответить
  • Изыди просвящения духх... Из ануса!
    Ответить
  • На "PHP" не переводится: "PHP" требует case сразу за switch.
    Ответить

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

Семь раз отмерь — один отрежь, guest!

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


    8