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

    −49

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    int* gaga(){
    	int x[2];
    	x[0] = 10; x[1] = 20;
    	int *p = x;
    	return p;
    }

    Однажды мне сказали, чтобы ретурнуть 2 значения нужно завести структуру или чота там еще, какие-то фразы которые я не понял.
    Но я луашник, я сделал по своему. И мне сказали что я ебанат.

    Запостил: _____, 18 Ноября 2016

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

    • Анскильные заедушные питушки используют массивы, чтобы вернуть много значений. Страдает пирфоманс.

      Пацаны возвращают пайпы:
      return BACKGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
      Ответить
    • А снаружи
      int * p = gaga();
      x = ((int (*)[2]) &p)[0];
      y = ((int (*)[2]) &p)[1];

      ?

      Edit: В глаза ебусь. Почему-то решил, что здесь используют тот факт, что sizeof(int *)==2*sizeof(int).
      Ответить
      • int main(){
        	int *s = gaga();
        	printf("%d %d",*s,*(s+1));
        	
        	return 0;
        	}
        Ответить
        • И конечно же возвращает лютую хуету?
          Ответить
          • Возращает нормально, 10 и 20.
            Ну как 10 и 20. Указатель на локальный массив.
            Ответить
            • Просто создание локальной переменной в виде массива создаёт его на вершине стека. Когда ты возвращаешь указатель на этот массив он указывает на область стека где были локальные переменные и ЛЮБОЙ вызов функции, заход в блок кода с объявлением локальной переменной может всё это перезаписать как угодно.
              Ответить
              • Напомнило, как Царь создавал «замыкания», которые разрушаются ЛЮБЫМ вызовом посторонней функции.
                Ответить
              • А ещё, в некоторых окружениях, эти данные за гранью текущего фрейма может засрать пробегавший мимо обработчик прерываний. Удачной отладки.
                Ответить
                • >>засрать пробегавший мимо обработчик прерываний
                  так нужен драйвер который запрещал бы прерывания на время твоей программы
                  Ответить
    • кстати, объясните как это работает:
      int arr[10];
      int (*ptr_to_arr)[10] = &arr

      Взял от сюда: https://learnxinyminutes.com/docs/ru-ru/c-ru/
      Ответить
      • См. спиральное правило
        http://c-faq.com/decl/spiral.anderson.html
        Ответить
        • Спасибка
          Ответить
        • эта питушня сишная, лучше бы такую хуиту через typeof() gcc-шный сделали http://govnokod.ru/19625
          Ответить
        • Си это такой язык, где даже живому человеку трудно понять код без сложных правил
          Ответить
          • Да нет там никаких сложных правил. Значки определяют идентификатор в порядке приоритета: сначала постфиксные, потом префиксные, скобками можно менять приоритет. Все как у обычных операторов. Ты же не ноешь, что разные приоритеты у сложения и умножения - это СЛОЖНА БЛИН.
            Ответить
            • Я замечал, что некоторые программисты считают необычную запись типов чуть ли не главной проблемой си. Мне кажется, это потому что они кроме хеловорлдов ничего не писали.
              Ответить
              • Я замечал, что некоторые неосиляторы ходят по сайту и пиздят что си это сложно.
                И когда им рассказывают что это не так, неосиляторы начинают рассказывать про хеллоуворлды.
                Ответить
                • Программирование - это сложно, дурачек. А на си еще сложнее.
                  Ответить
                  • ты хуй
                    Ответить
                  • Это вы просто ТКТП не разбирали.
                    Ответить
                    • > ТКТП

                      Теория Категорий и Топологических Пространств?
                      Ответить
                      • Транспортная компания тупых пёзд
                        Танковый командир танковой пехоты
                        Таварищеская коммуна таганрогских предприятий
                        Тут какой-то тотальный пиздец
                        Трактор компании Тетя Петрович
                        Так как ты пидор

                        Тянские куни только платно
                        Ответить
                      • Топологическая квантовая теория поля. Близко связана, кстати.
                        Ответить
                  • Русский язык - это ещё сложнее.
                    Ответить
            • Видимо надо было выделять зеленым
              Ответить
            • Именоо поэтмоу я за 'J' и S" Forth".
              Ответить
    • Рил ебанат
      Ответить
    • int *f() {
          int a = 10;
          int b = 20;
          return &a;
      }
      Ответить
      • Стек же вниз растёт.
        Ответить
        • Стек растет вниз, а переменные во фрейме размещают вверх.
          https://godbolt.org/g/WzNoCz
          Ответить
          • А шланг делает наоборот https://godbolt.org/g/YMIz5d
            Ответить
          • А гцц 6.2 вообще нулевой указатель возвращает. Ибо нехуй.
            https://godbolt.org/g/Luyoys
            Ответить
            • Трудно будет Царям грядущих лет.
              Ответить
              • Ничего, они ещё заставят конпеляторы по струнке -O0 ходить.
                https://godbolt.org/g/PEUtt2
                Ответить
                • Разве volatile должен так компилироваться? В коде есть чтение из p, а в получившемся ассемблере нет.
                  Ответить
                  • А, нет. В шары долблюсь.
                    Ответить
                  • Да и вообще volatile относится не к p, а к данным, на которые он указывает.
                    Ответить
                    • хахаха запутался!))

                      Вот за что я люблю си, так это за то что в дефинициях люди путаются.
                      Ответить
    • Надо было в куче массив создавать. Или вообще выделять память вызовом функции операционной системы, а то вдруг куча освободится после завершения программы.
      Ответить
      • Написать
        static int x[2];
        во второй строке и не мучаться с кучей
        Ответить
        • А потом словить race condition. Самое оно.
          Ответить
    • Давай может быть ты почитаешь что-нибудь про стек и автоматические переменные сначала, а потом будешь пытаться писать?

      Ты же даже азов языка не понимаешь, а всё туда же.
      Ответить
    • https://github.com/dennis714/random_notes/blob/master/stack.md
      Ответить
      • Интересно, где он собирается искать переменные на -O2 и выше...
        Ответить
        • надо volatile делать
          Ответить
          • А volatile разве обязывает конпелятор выделять под локальную переменную ячейку памяти, если ты на неё явно не брал указатель? Вроде нет. Емнип, стандарт обещает только сохранение взаимного порядка обращениё к volatile переменным в текущем потоке.
            Ответить
            • Ну да, он декларирует, что не только запись, но и чтение volatile переменной считается побочным эффектом, и ничего про хранение там нет.
              Ответить
              • Ну т.е. компилятор вполне может разместить переменную в регистре и честно читать и писать в этот регистр :)
                Ответить
                • достаточно один раз взять адрес у переменной чтобы компилятор не пихал ее в регистр, нет?
                  Ответить
                  • Да. Но если она не volatile, то компилятор, в теории, может понять, что адрес далеко не убежит и поменять все эти *ptr прямо на обращение к регистру... Видимое поведение программы же не пострадало.
                    Ответить
                    • Можно сделать достаточно жирный массив, на который регистров не хватит
                      Ответить
                      • лол, а разве можно вообще массив в регистр пихать?
                        вообще какможно сказать register char fo[34] ?
                        Ответить
                        • Напихал тебе массивов в регистр, проверь.
                          Ответить
                          • https://www.google.ru/search?q=%22%2C+%D0%BF%D1%80%D0%BE%D0%B2 %D0%B5%D1%80%D1%8C.%22&oq=%22%2C+%D0%BF% D1%80%D0%BE%D0%B2%D0%B5%D1%80%D1%8C.%22& aqs=chrome..69i57.743j0j1&sourceid=chrom e&ie=UTF-8#newwindow=1&q=%22%2C+%D0%BF%D1%80%D0%B E%D0%B2%D0%B5%D1%80%D1%8C%22+site:govnok od.ru
                            Ответить
                        • > можно вообще массив в регистр пихать
                          Можно. Всякие SIMD инструкции (SSE и т.п.) как раз массивами оперируют (маленькими).
                          Ответить
                          • конечно, SIMDами пользуются когда тебе нужно сделать операцию для массивом. А когда у тебя просто 20 байт в памяти лежит ен думаю что компилятор будет пихать в регистр их.

                            Вообще кл. слово register делает мне смешно: машины вообще бывают безрегистровые (виртуальные)
                            Ответить
                            • > когда у тебя просто 20 байт в памяти лежит
                              Ещё как пихает, по крайней мере для копирований/занулений... У меня так прога умерла (SSE не было включено). Причём это был даже не массив, а просто присваивалась структурка байт на 30.

                              > кл. слово register
                              Дык оно ни к чему не обязывает, емнип, просто хинт.
                              Ответить
                              • орлы?
                                то-есть конпелятор так memcpy может сделать?

                                >>просто хинт

                                разумеется:) но всё таки это деталь реализации, пролезшая в стандарт, верно?
                                Ответить
                                • > так memcpy может сделать
                                  Да. Вместо memcpy воткнуть пару mov'ов через sse.
                                  Ответить
                                  • охуеть! (побежал смотреть что там мой компилятор нагенерит)

                                    Отстал я от жизни
                                    Ответить
    • #include <string.h>
      #include <stdio.h>
      #include <alloca.h>
      
      int* gaga(void * dest)
      {
      	int x[2];
      	x[0] = 10; x[1] = 20;
      	memcpy(dest, x, sizeof(x));
      	return dest;
      }
      
      int main()
      {
      	int *x = gaga(alloca(sizeof(int[2])));
      	printf("%d %d\n", x[0], x[1]);
      	return 0;
      }
      Ответить
      • хотя можно еще void *dest кастануть в указатель на int но GCC тогда хуевей оптимизирует
        https://godbolt.org/g/eRHVPZ
        хотя clang наоборот
        Ответить
    • Нуб и опозорился
      Ответить
    • интересно, вот почему нельзя объявлять тип возвращаемого значения прямо в определении метода?
      struct { int a, b; } someMethod() { return {3,5}; }
      Ответить
      • нельзя просто так взять и объявить тип возвращаемого значения прямо в определении метода.
        Ответить
      • А покажите пример использования такого метода
        Интересно просто
        Ответить
        • Ну например хочется тебе проверить, что у тебя двоичное дерево - дерево поиска. Это можно сделать рекурсивно: проверяешь, что оба поддерева - деревья поиска, и что максимальный элемент левого меньше значения в корне, а минимальный правого - больше.
          {int min, max; bool ok} isBst(Derevo derevo) {
              auto l = isBst(derevo.left);
              auto r = isBst(derevo.right);
              return {min: l.min, max: r.max, ok: l.ok && r.ok && l.max <= derevo.value && r.min >= derevo.value};
          }

          похуй на базу рекурсии
          Удобно же. Вводить структуру IsBstResult только для возврата нескольких значений из функции - беспонтово, туплы непонятные нифига (сначала min или max?). Так что сейчас я бы min и max через параметры вернул. Но ведь параметры - это параметры, а возвращать надо через ретурн.
          Ответить
          • ну ладно, если у нас есть вывод типов и комплиятор поймет что-то типа

            auto a = isBst(hui);
            a.min..

            то ладно
            -------

            только это си, а не с++, и auto тут значит СОВСЕМ другое)
            Ответить
        • Мне как-то раз понадобилась 3д точка в пространстве сигнал/частота/отсчет, причем использовалась буквально в одном месте в коде. Я бы с радостью писал std::tie(level,freq,index) = myMethod(); где внутри myMethod везде return {level,freq,index};

          А через tuple не наглядно
          Ответить

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