Комментарии 108
Через некоторое время при проведении собеседования вспомнилась эта шутка.
Очень надеюсь, что это было собеседование с самим собой в зеркале 1-го января и вам не пришло в голову принимать решение о найме программиста на основе этой бредятины.
Да не сказал бы. Посмотреть тот же hh и сравнить вакансии c++ и какой-нибудь node.js
Ну, я думаю что в случае ключевых слов JS и работа — node.js первое, что приходит в голову. Все эти angular/reactive/matreshka, которые через здоровенный автоматизированный пайплайн выдают пользователю кнопочку "сделать хорошо" на одностраничнике. Мало кого сейчас интересуют рисователи кнопочек на jQuery, если вообще интересуют.
Аналогично PHP работает на серверной стороне, да и также как и PHP по большей части нацелена на веб. Можно конечно проворачивать такое и с c++, но едва ли такая вакансия будет настолько же оплачиваема и востребована как знаток ноды или того же пхп.
От минусанувшего хотелось бы узнать что не так с предыдущим комментарием.
Была одно время мода на такого рода собеседования ( там еще триграфы любили спрашивать ), но казалось бы уже прошла.
На ARM мы получим исключение если участок памяти находится между сегментами
А можете пояснить, что вы подразумеваете под понятием "сегментам" на ARM,
и ARM с MMU или с MPU имеется ввиду?
Про проблемы с выравниванием я знаю, и по крайней мере у gcc есть несколько ключей,
для генерации предупреждений по этому поводу, на x86
с этим тоже можно кстати столкнуться,
например если компилятору "сказать" что данные выравнены и заставить его сгенерировать код для работы скажем с AVX, а потом дать на вход невыровненные данные.
Меня интересовало как раз что за сегменты (на arm скажем никаких сегментов в терминах i386 нет) и что за дырки между ними, но судя по все это было просто недопонимание.
на котором кандидату ( видимо на должность C программиста ) задавали бы вопросы про оператор «запятая», сложение числа со строкой и приоритет операций? Готов человек блестяще решивший эту задачку писать операционные системы, базы данных или какие-нибудь cache oblivious алгоритмы
Так это совершенно разные проверки. Если вам нужен человек знающий хорошо язык XYZ и при этом владеющий дополнительно навыками A, B, C, проверять вы будете и то, и другое, верно?
1). Категорически неочевидно как из блестящего владения оператором «запятая» следует хорошее знание языка C
2). Кроме того само по себе знание C не нужно никакому бизнесу, кроме разработчиков компиляторов. «Знаешь C? Ну, возьми с полки пирожок. Нам интересно как ты поможешь нам в разработке нашего вэб-сервера».
3). Собеседование — это формат переговоров, весьма сжатый по времени. В текущей реальности только гугл и сопоставимые компании могут мурыжить кандидатов 6-ю собеседованиями, для более приземленных компаний нужно за час-полтора принять решение о, том, будем ли мы сотрудничать с этим человеком. Тратить это время на разговоры об операторе запятая — это похоже на «Окей, леди и джентльмены, у нас час на то, чтобы заключить эту важную для всех нас сделку, так что давайте для начала станцуем танец маленьких утят»
2). Нужно, если работаете программистом на С. Вы не поверите, но есть устройства, где язык С единственный язык программирования.
3). Согласен.
Фундаментальные мировоззренческие вещи затронули.
1). Категорически неочевидно как из блестящего владения оператором «запятая» следует хорошее знание языка C
Никак. Необходимое, но не достаточное условие.
2). Кроме того само по себе знание C не нужно никакому бизнесу, кроме разработчиков компиляторов. «Знаешь C? Ну, возьми с полки пирожок. Нам интересно как ты поможешь нам в разработке нашего вэб-сервера».
Ну, наверно, если гражданин нанимает работников, проверяя знание языка Си, то именно им он как раз и нужен, не? Знание этого языка является необходимым условием для приема на работу именно в эту фирму. Необходимым, т.е. проверка на знание A, B и C из моего предыдущего комментария последует отдельно.
Собеседование — это формат переговоров, весьма сжатый по времени. В текущей реальности только гугл и сопоставимые компании могут мурыжить кандидатов 6-ю собеседованиями, для более приземленных компаний нужно за час-полтора принять решение о, том, будем ли мы сотрудничать с этим человеком.
Даже в маленьких конторах проводят по 2-3 собеседования, это нормально.
Никак.
Итак, мы проверяем знание оператора запятая, хотя из этого мы не можем извлечь никакой информации о знании языка C. Вроде бы как напрашивается вывод…
Ну, наверно, если гражданин нанимает работников, проверяя знание языка Си, то именно им он как раз и нужен, не?
Не. Это как: «Я взял на улицу зонт, следовательно идет дождь» — не следует.
проводят по 2-3 собеседования, это нормально.
У меня другое мнение и оно подтверждается ( моей ) практикой, но это уже совсем оффтопик. В любом случае, даже если у нас 3 собеседования — тратить время просто так не надо.
Итак, мы проверяем знание оператора запятая, хотя из этого мы не можем извлечь никакой информации о знании языка C. Вроде бы как напрашивается вывод…
Вы непоследовательны и нелогичны.
Я сказал, что это необходимое, но не достаточное условие. Вы понимаете, что это значит? Это значит, что мы проверяем, не отсутствует ли данное знание у человека, и выбраковываем по факту отсутствия в качестве одного из этапов.
Не. Это как: «Я взял на улицу зонт, следовательно идет дождь» — не следует.
Человек объявляет, что набирает разработчиков, знающих язык Си и проверяет это знание тем или иным образом. Ваш довод, о том, что данный кандидат, зная Си, может не знать других вещей, необходимых в работе, не отменяет необходимость проверки на знание языка. Эти две проверки связаны через конъюнкцию.
На C нужно драйвера писать. И да, кто-то переписывал серверную обработку "космических боев" с PHP на C++.
/* Mark: If there's one thing you learn from this code, it is this...
Never, ever fly Air France. Their customer service is absolutely
the worst. I've never heard the words "That's not my problem" as
many times as I have from their staff -- It should, without doubt
be their corporate motto if it isn't already. Don't bother giving
them business because you're just a pain in their side and they
will be sure to let you know the first time you speak to them.
If you ever want to make me happy just tell me that you, too, will
never fly Air France again either (in spite of their excellent
cuisine).
Update by oej: The merger with KLM has transferred this
behaviour to KLM as well.
Don't bother giving them business either...
Only if you want to travel randomly without luggage, you
might pick either of them.
*/
здесь
#define + -
#define -> .
?
Вторая строка: после первой же сборки вражеская закладка будет обнаружена.
Но есть нюанс: я считерил. Вообще не пришло в голову, что Р можно сделать функцией. Почему-то сразу подумал про макрос, и написал
#define P(x) 0
(хотя макросы не люблю и без крайней необходимости обычно не использую).Эк вас занесло. 3 секунды: http://cpp.sh/6wx7
Оптимизация хвостовой рекурсии с аккумулятором? Круто, давно пора, я наверное еще 2 года назад удивлялся, что ее нет. Самое сложное — представить как можно больше паттернов рекурсий таким образом. Возможно, даже все представимы
Только что-то из патча не совсем понятно, как это сделано. Просто присвоили одному хитрому макросу результат другого хитрого макроса ???
#define for(...)
#define P(...)
int main() {
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);
}
Интересно, что понимается под словом "работает".
int main() {/*
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);
*/}
void P(const char *s){
printf("%s", s);
}
в итоге напечатают красивую картинку в консоли. Понятно, что если сделать char *u,
то можно разными строками получать разные картинки. Я пытался сделать
int k = 8; /* 0, 1, 2 .. 16 */
int *u = &k;
Ничего красивого не вышло. Потом прочитал спойлеры и разочаровался. И неинтересно, и не смешно. Чувствую себя обманутым! После такого собеседования я бы и сам к вам на работу не пошел!
Вопрос к автору — я вместо функции P сделал так:
#define P(x) printf(x)
Это как-то карается? А еще у меня ни ретурнов, ни инклюдов — ворнинги сыплются, но все работает корректно (опять же, опыт кодгольфа).Да, это main, поэтому я опустил return.
Функции из libc не имеют отношения к инклюду — инклюд влияет только на подтягивание объявлений функций. Фокус в том, что printf (и поразительно большое число других функций) имеют прототип, эквивалентный прототипу по-умолчанию — возвращают int, принимают то, что в них передали.
#define P(x) printf(x)
Можно и так. Смысл не меняется. Return — будет в ворнинге
И этот человек догадался, что этот код «рисует лабиринт в stdout»? Лично у меня, когда я увидел эту строчку, возникло желание не понять, что оно делает, а тупо нейтрализовать и просто удовлетворить формальным требованиям (это несложно сделать даже без макросов):
int main() {
int R = 0;
int e = 0;
int C = 0;
char *u = 0;
int (*P)();
for( ; P("\n"), R-- ; P("|"))
for(e=C; e--; P("_" + ( *u++/8)%2))
P("| " + (*u/4)%2);
return 0;
}
Или всё-таки предполагается, что на соискатель должен догадаться об оригинальном назначении кода и написать программу, которая бы строила лабиринт?
Практически на рефлексе: слова, написанные целиком капсом — макросы. Сразу после этого заставить пример компилироваться и ничего не делать (или делать всё, что нам заблагорассудится) — тривиально (аргументы макросов можно не использовать вообще — пример резко упростится).
Но разбор прочёл не без интереса.
// Example program
#include <stdio.h>
extern "C"
{
int R = 5, *u, e, C, x = 5;
void P( const char * ptr )
{
C = R;
printf( "R:%d, u:%p, e:%d, C:%d, x:%d ptr:%p '%x,%x,%x''%c%c%c'\n"
, R, u, e, C, x, ptr
, *(ptr+0), *(ptr+1), *(ptr+2)
, *(ptr+0), *(ptr+1), *(ptr+2) );
return;
}
int main()
{
u=&x;
for ( ; P("\n"), R--; P("|"))
for (e = C; e--; P("_" + (*u++ / 8) % 2))
P("| " + (*u / 4) % 2);
}
}
Нет, действительно, писать всё в одну строчку, плюс все эти *p++, это чистой воды издевательство на тем, кто этот код будет разбирать.
Ну и в припадке ностальгии, вспомнил знатный холивар с коллегой, который был за if( some ) вместо if( some != 0 ). Хотя, это уже не так страшно и воспринимается более менее нормально.
Вы потеряли пробел в строке "_ ", что не лучшим образом сказывается на понимании, что вообще происходит.
Меня смутило то, что во внутреннем цикле вызывается
P("| " + BIT_SET(*u, 2));
P("_" + BIT_SET(*u, 3));
u++;
Вроде бы конструкции однотипные, но без пробела логика получается подозрительно разная.
Так вот, смутило это меня в достаточной степени, чтобы найти
Это один из победителей IOCCC 1985, shapiro.c by Carl Shapiro, код рисует лабиринт в stdout. И да, там есть этот самый пробел. =)
В процессе поиска нашелся еще и занятный пост про обфускацию C и лабиринты.
Эмулятор процессора, без проблем запускающий CP/M с BASIC-ом внутри.
только почему-то мой склероз в свое время мне подсказывал maze.c а надо было shapiro.c искать
#include <iostream>
using namespace std;
void P(const char *str) {
cout << str << endl;
}
int main() {
int e;
char *u = "11111111111111";
int R = 3;
int C = 5;
for(; P((char *)"\n"),R--; P((char *)"|")) {
for(e=C; e--; P("_"+ (*u++/8)%2)) {
P(" | "+ (*u/4)%2 );
}
}
return 0;
}
Выводит:
| _ | _ | _ | _ | _|
| _ | _ | _ | _ | _|
| _ | _ | _ | _ | _|
1. что-то с отступами не задалось
2. это С, а не С++ (см. функцию Р)
3. код править по заданию нельзя. (char *) — зачем?
Что-то не верю я в то, что она такое выводит.
#include <stdio.h>
void P(const char *str) {
printf("%c", *str);
}
int main() {
int e;
char *u = "11111111111111";
int R = 3;
int C = 5;
for (; P("\n"), R--; P("|"))
for (e = C; e--; P("_" + (*u++ / 8) % 2))
P("| " + (*u / 4) % 2);
return 0;
}
Таки выводит, правда, без лишних пробелов (см изменения в P(char*)).Теперь берёте на работу?)
Когда я вижу такие задачи на собеседовании — я говорю "до свидания, всего хорошего вашей компании". Дальше обычно разговаривать не имеет смысла.
2. Что-то не понял, где «C» декрементируем?
Тест на знание языка Си, найденный в первоапрельской шутке