Безумные задачки

    После бурной дискуссии у меня возник вопрос: а, действительно, как много людей, знающих (или считающих что они знают) C++ могут ответить на вопрос, подобный «простейшему тесту» из обсуждаемой статьи.

    #include <iostream>

    int test(int x) {
      static const int y = test(x + 1) * 2;
      return x + y;
    }

    int main() {
      std::cout << test(42) << std::endl;
      std::cout << test(0) << std::endl;
    }

    Вопросы:
    1. Для какой версии GCC будет работать эта программа?
    2. Что она выведет на экран?
    3. Как отрефакторить функцию test() чтобы она стала совместима со стандартом (и с GCC 4.2, соответственно)?

    Ну и парочка более простых примеров (примерно как задачка номер два там):
    4. Как описать внутри класса функцию классу не принадлежающую (то есть не являющуюся ни статическим, ни динамическим методом класса)?
    5. Зачем эта возможность нужна в C++?

    Ну и напоследок вопрос: а стоит ли задавать подобные вопросы на собеседовании?

    P.S. Подсказки пишите белым по белому, как обычно…
    Поделиться публикацией

    Комментарии 61

      0
      1. Не знаю. Привязываться к компилятору в данном случае вообще дело не очень благодарное.
      2. У меня вывела "...recursive_init_error..." :)
      3. Непонятно, что ты хочешь получить в итоге. :) Представил код который не запускается и просишь отрефакторить - это сильно. :)

      4. ты про static-функции внутренних классов?
        0
        1. Функция приведена в The Annotated C++ Reference Manual как работающая. С тех пор и компиляторы и стандарты поменялись.
        2. Это зависит от версии компилятора и версии реализованного в нём стандарта.
        3. А вы как думали ? Представьте что вам дали библиотечку, которая когда-то собиралась и работала, а теперь падает. Что делать будете ? Заметьте что PHP-программистов просят подобное проделать сходу, на бумажке, не обдумывая.

        4. Это одно из решений, но "совсем не про то". Сейчас изменю формулировку, спасибо.
          0
          3. Я же знал, что библиотечка делает. :) А тут мне сложно представить, что функция возвращает
          4. Я догадался, что не то. Просто других вариантов нет. :)

          PS. Давай на "ты".
            0
            3. А что она может возвращать ? Если она вообще что-либо возвращает ?

            4. Есть. И, как ни странно, эта возможность наоборот отсуствует в ARM'е - её в какой-то момент добавили. Hint: когда писался ARM шаблоны в C++ были в зачаточном состоянии (но это скорее ответ на 5й вопрос, чем на 4й).

            P.S. Ок...
              0
              3. аргумент + число :) какое число пока мне неизвестно.
              4. я ARM не читал. я The C++ Programming Language: Special Edition читал только. Затрудняюсь ответить, в общем-то.
                0
                3. Ну тут-то уж чистая логика. Если бесконечной рекурсии нет и вопрос 3 имеет смысл, то там вариантов-то остаётся с гулькин нос.
                4. В ARM'е этой возможности нет - её добавили позже и практический смысл она имеет только для шаблонов (хотя может быть использована и без шаблонов, но в такой постановке особого смысла в ней нет).

                Я завтра ответы напишу, там всё несложно...
                  0
                  3. (x+1)*2? я уже устал :)
                    0
                    Ну... Более или менее: нужно избавиться от рекурсии.


                    int test(int x){
                      static const int y = (y + (x + 1)) * 2;
                      return x + y;
                    }

                    Тот факт что это - правильный код уже на современном C++ и он даёт вполне определённый (а не рандомный) результат тоже является для многих откровением...
                      0
                      Мдя. Не знал, что переменную можно определять через себя же... :(
                        0
                        Остальное в принципе понятно.

                        (int x = x) == (int x)
                        статические переменные всегда инициализируются нулем по умолчанию - в присваивании справа y == 0.
            0
            ARM давно устарел. За такой код нужно отрывать руки. Я давно на С++ не писал, но на С для устройств всё ещё пишу и мне сложно представить компилятор который позволит такое присвоение константе, это неконстантное выражение и иное позволял разве уж очень древний компилятор.

            Сишников эмбедеров я тэстирую:
            — битовая арифметика и представление чисел, структуры, битовые поля, юнионы, представление форматов данных
            — указатели vs масивы
            — понимание в что твой код отранслируется, параметры на стеке и по ссылке, емуляция или заменители функций стандартной библиотеки( stdlib нет, выделения памяти в микроконтролере нет)
          0
          почему бы не задвать вопросы сразу по асемблеру...
            0
            Создай еще одну тему, теперь насчет асма :)
            0
            > Ну и напоследок вопрос: а стоит ли задавать подобные вопросы на собеседовании ?
            по-моему только если маньяка ищете, свихнувшегося на c++...
              0
              Ну... Ведь от от PHP'шников чего-то подобного ждут... Вот я и засомневался... Так-то я был того же мнения... Если PHP-программисты должны знать историю своего любимого языка, то почему от программистов на C++ такого не требуют ? Рассказать как можно было присваивать указателю this в конструкторе в ранних версиях C++ или как можно передавать в постфиксный operator++ значение (он ведь описывается обычно как T operator++(T&,int), правда: так вот зачем там второй аргумент и как его можно поиспользовать?).
                0
                Нет. Все вопросы, что были там обсуждаются в официальном php manual, прочитать который (без описания библиотеки php) можно за пару часов.
                  0
                  Всё что я тут спрашиваю находится в ISO/IEC 14882-2003 и ARM'е (фактически - стандарт языка до ISO/IEC 14882-1998), уж извините. Так что если от претендентов требовать знания мануала, то они это тоже должны знать. В частности ответ на вопрос 4 содержится в разделе 11.4, пункт 5.
                    0
                    ARM - книга. Её нужно покупать. Где достать стандарт C++ я не знаю (я-то найду, если мне нужно будет). По стандарту учить C++ я не собираюсь - это идиотизм.
                    PHP Manual - это то, что можно взять и посмотреть на официальном сайте PHP.

                    Извини, но разница в реале, огромная между этими двумя вещами.
                      0
                      Почему учить C++ по его описанию - это идиотизм, а PHP - нет ? PHP Manual - это такой же справочник, как ISO/IEC 14882-2003.
                        0
                        Ты PHP Manual читал? :) Прочти страничку. Поймешь разницу. Это книга же по сути. ОЧЕНЬ простая.

                        В C++ для того, чтобы разобраться с указателями очень много времени с самого начала нужно, даже при помощи книг нормальных и понятных. А не стандарта...
                          0
                          Умение манипулировать с указателями вообще никаких книг не требует. Либо ты умеешь с ними манипулировать, либо нет. Я могу с лёгкостью объяснить как устроена работа с C'шными указателями на PHP или Fortran'е - это от языка вообще не зависит.
                          А PHP... Порождает простота табличек типа этой - просто закачаисся как просто всё:
                          TRUE FALSE 10-1"1""0""-1" NULL array()"php"
                          TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE
                          FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE
                          1 TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
                          0 FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE
                          -1 TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE
                          "1" TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
                          "0" FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
                          "-1" TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE
                          NULL FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE
                          array() FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
                          "php" TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
                            0
                            Табличку не понял абсолютно :(
                              0
                              Точнее - откуда взялись TRUE, FALSE, 1, 0, -1, "1", "0", "-1", NULL, array(), "php"
                                0
                                Из того самого мануала, который вы, по вашим словам, вроде как читали и блюдёте: вот тут вот.
                                  0
                                  Читал, но не все. :) Этой таблички не видел. Меня просто смутило, что ты тут сначала про указатели, потом сразу табличку приводишь со значениями взятыми непонятно откуда.
                                    +1
                                    Но ведь вокруг этой таблички все пляски с бубнами в 1й задаче предыдущего топика! Я применяю простые правила: если в переменной строка или число - можно использовать ==, если что-то другое - то только === , всё остальное - от лукавого. Ибо разбираться с "равенством", которое не является отношением эквивалентности (ни транзитивности, ни симметрии) - нет ни малейшего желания. Отношу эти сведения туда же, куда все тонкости процесса инициализации статических переменных в C++: прикольная информация, которая раз в 10 лет может и пригодится, но вообще - излишество.

                                    Но тут вдруг выясняется что это - прям край необходимое знание для PHP-программиста...
                                      0
                                      Честно - не помню я этой таблицы в упор. Помню только то, что тут написано (но ссылки на показанные тобой таблицы я не помню...)
                                        +2
                                        И считаю, что PHP-программист это знать всё же должен. Т.к. сравнивать приходиться ну очень часто.

                                        PS. Некоторые даже об операторе === не знают...
                                          0
                                          Вообще-то в табличке ничего "аж такого" нету... все логично, если хоть немного кодить в ПХП... и зачастую это все очень удобно...
                                            0
                                            Позволю себе не согласиться. :) Знать это нужно. Но "логично" и "удобно" - это уж извини...
                                              0
                                              а что нелогично? и неудобно?
                                                0
                                                Угу. В PHP вообще много всего нелогичного и неудобного... Всё ИМХО.
                                                  0
                                                  ну это уже перебор...
                                                  Сказать, что все плохо - легко. Хочется, все же, конкретики...
                                                    0
                                                    Попиши на Ruby или Python'е... Поймешь, почему мне не нравиться PHP...

                                                    А вообще - отсутствие нормальных namespace'ов (модулей, называй как хочешь) и нормальной стандартной библиотеки (ООП'шный язык, который не имеет ни нормального класса строки/массива и т.д...). В котором непонятно откуда возникают ограничения (почему я не могу написать test()[0], если test возвращает массив). И т.д.
                                                      0
                                                      Да ладно вам, Ruby идиологически другой чем PHP. Всё равно что сравнивать подлодку с боингом
                                                        0
                                                        Что значит "идеологически другой"? Может тогда языки вообще сравнивать нельзя между собой?

                                                        Оба языка используются для разработки web-приложений - вот я их и сравниваю.
                                                    0
                                                    З.Ы. я без наездов, просто интересно :)
                                                    0
                                                    "php"==0
                                                    array()==NULL && NULL!=array()
                                                    =0.o=
                                  0
                                  Да и стандарт еще достать нужно... Как я понял, на сайте ISO его бесплатно скачать нельзя?
                                    0
                                    Нет. Для таких целей есть Google...
                                      0
                                      Вот потому PHP Manual и C++ Standard - это разные вещи.
                              0
                              официальный мануал довольно скуден
                              нюансов фатически нигде нет
                              вы хотя бы посмотрите комментарии на php.net к статьям мануала, такие неожиданные особенности встречаются...
                              плюс очень не хватает нативного описания STL
                              0
                              должны знать историю" - не историю. основные отличия между php4 и php5. правда это скоро в прошлом будет, т.к. php4 умер.
                                0
                                Либо я не уже разучился понимать русский язык, либо одно из двух. Как-то мне всегда казалось что отличие между тем, что "было" и тем что "стало" - это как раз история и есть.
                                  0
                                  Эмм. Должны знать это. Опять же - одна глава в мануале.
                            0
                            По поводу работы программы..
                            - ошибка с рекурсией
                            - разьве не должны функция int main обязательно возвращать значение?

                            По поводу вопроса 4 вы не про дружественные (friend) функции имеете ввиду? Используется для расширения интерфейса класса.

                            Если в чём-то ошибаюсь прошу поправить)
                              0
                              1. Читай комменты - не везде это так.
                              2. оно само ноль вернет
                              3. не про дружественные - сам ответил. почитай еще раз. дружественные - это как раз наоборот.

                              ну, собсно, во всем ошибаешься :)
                                +1
                                2. Оно возвращает не ноль, а "что бог на душу положит" (вернее что в EAX случайно попадёт).

                                4. Как раз-таки про дружественные функции. Они могут вообще никак не быть связаны с классом!

                                #include <iostream>

                                class test {
                                 private:
                                  friend void notest(int x) {
                                    std::cout << "Notest called, test is not needed, x = " << x << std::endl;
                                  }
                                };

                                int main() {
                                  notest(42);
                                }

                                Ничего так ? Объявили функцию в классе test в разделе private, но использовать её можно без всякого класса test вообще! А вот зачем такие чудеса нужны ?
                                  0
                                  пипец. я как-то дружественные функции знал в другом ракурсе.
                                    0
                                    И кому эта функция дружественная?
                                      0
                                      Ну как - она дружит с классом test, то есть может ходить к нему в гости без спросу. Но если она не хочет этого делать - никто её не заставляет...
                                        0
                                        Я уже понял. просто я дружественные функции внутри класса не объявлял никогда. наоборот - объявлял вне класса. В классе определял только саму "дружбу". Страуструпа читал давно, не помню уже, что он по этому поводу говорил (если вообще что-то говорил).
                                      0
                                      Я дружественные функции всегда объявлял вне класса наоборот.
                                        0
                                        Дык. Так всегда можно было делать. Но с принятием стандарта можно в классе не только описывать дружественные функции, но и определять их - и это не "просто так получилось", это было специально сделано.
                                          0
                                          Понял. Пасиб.
                                            +1
                                            А вот зачем это нужно... Дело в том, что нешаблонная функция внутри шаблонного класса - она всё равно не шаблонная, а это значит что она по другому участвует в системе типов. Пример "почти из жизни" такой:
                                            template<typename T>
                                              class Complex {
                                               public:
                                                Complex(T r, T i = T()) : re(r), im(i) {
                                                }
                                               private:
                                                T re, im;
                                                friend Complex<T> operator+(Complex<T> c1, Complex<T> c2) {
                                                  return Complex<T>(c1.re + c2.re, c1.im + c2.im);
                                                }
                                              };

                                            main() {
                                              Complex<double> i(0,1);
                                              Complex<double> a=1+i;
                                            }

                                            Если ты вынесешь operator+ из класса наружу, то тебе придётся сделать его шаблонной функцией и в последней сточке main'а возникнет ошибка которую ты запаришься исправлять (хотя это и можно исправить - это уже 6й вопрос: как?)...
                                              0
                                              Хм. Действительно... Не сталкивался с такими проблемами (или сталкивался, но не знал, что это именно такая проблема). Хотя я на C++ и не пишу особо много - только лабы для универа.
                                    0
                                    1. Ошибка с рекурсией - да, но не так давно это была вполне законная и допустимая программа.
                                    2. Нет, это не Java: "Flowing off the end of a function is equivalent to a return with no value."

                                    4. Угу. Они самые. Осталось только понять: зачем. Напоминаю: в ранних версиях C++ такой возможности не было, её специально ввели и в следующей версии стандарта для них будет отдельный раздел! Если люди вкладывают в это столько сил, то это, наверное, кому-то для чего-то нужно ???
                                    0
                                    как много людей, знающих (или считающих что они знают) C++


                                    тогда уж, "знающих GCC", а не С++ вообще
                                      +1
                                      считаю уважающий себя программер должен бежать от таких работодателей) уж лучше в грузчики.
                                        0
                                        Хм. Очень странная комбинация вопросов. Особенно, номер 3. А в какую сторону надо изменять (зачем такое сложное слово — рефакторить?) функцию. Она что вообще должна делать?

                                        И про собеседование. А зачем нужны такие вопросы? Это всё-равно, что у столяра спрашивать: а вы знаете, в каком году в наших отвёртках появились стальные сердечники? Нет, ну реально. Программист должен выполнять работу. Знание тонкостей C++ ещё не означает, что он сможет все эти тонкости собрать вместе и написать нормальную осмысленную программу.

                                        На собеседовании надо давать задачи, которые покажут способен ли программист решать задачи, которые перед ним будут поставлены. Вот…

                                        А ещё можно сказать вот о чём. Если я, ну например, разрабатываю операционную систему и приглашаю программиста на работу и прошу его, например, написать драйвер мышки, то я буду оценивать того кандидата выше, который представит более эффективное и простое решение, а не того, который нашпигует программу хитростями и тонкостями из Си++.

                                        Например, если он завернёт работу с портами в классы, то я его явно ещё и попрошу доказать, почему он считает такое решение эффективным. При этом не только с точки зрения производительности, но и с точки зрения общей философии программирования.

                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                        Самое читаемое