Продолжаю в свободное от работы время немножко преподавать.
Студенты написали (и довольно неплохо) первый в этом году тест, после шести первых лекций, посвященных базовому C++ (всё что можно рассказать человеку со знанием C, не рассказывая ничего про ООП -- включая простые шаблоны функций и decltype/auto).
В связи с чем хочу выложить этот тест для местной общественности. Может будут какие-нибудь предложения, замечания, всё такое.
UPD: Всем спасибо, как я понял, профессиональное коммьюнити сочло тест скорее неудачным. Я всех прочитал и скорее всего я учел ваше мнение, даже если по моему ответу вам кажется, что это не так. Я склонен свернуть дальнейшее обсуждение со своей стороны, поскольку в общем мне всё ясно по заданному вопросу.
Моё ИМХО:
Кажется этот тест скорее по "Си с классами"
Много вопросов про указатели, макросы, printf-ы, но нет например вопросов специальные функции (конструкторы, деструкторы, операторы переноса или копирования), про STL алгоритмы, про безопасность исключений (хотя спорно), про RAII, и всего что про "современный C++".
Мне кажется этот доклад имеет смысл посмотреть: http://www.youtube.com/watch?v=YnWhqhNdYyk
После такого у студентов охота осваивать С++ не пропадает?
Да, и почему вы выделяете ООП как фичу С++? ООП и на чистом С можно успешно применять (хоть и не так удобно).
Человек со знанием С, но без знания ООП, наверняка начнет пилить тот самый "С с классами".
ЗЫ
не специфицирован
лучше писать "не определен"
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Здравствуйте, Tilir, Вы писали: T>В связи с чем хочу выложить этот тест для местной общественности. Может будут какие-нибудь предложения, замечания, всё такое.
Я бы этот тест завалил — просто скомкал бы бумажку и ушел домой. Почему-то у меня за 10 лет работы с С++ никогда вопросов, связанных с тестовыми, не возникало. Возможно, потому что мне практически никогда не приходилось копаться в чужом говнокоде, вместо этого я писал программы для людей.
1. Тут все режет глаза. Не хочу разбираться в этом спагетти.
2. Здесь написана дичь, за такие записи нужно увольнять.
3. Оба варианта полезны по-своему, но первый устарел, потому что есть enum class.
4. Такие макросы в топку.
5. Запустить компилятор и проверить.
Re[2]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Went, Вы писали:
W>Возможно, потому что мне практически никогда не приходилось копаться в чужом говнокоде, вместо этого я писал программы для людей.
Мне просто интересно, как вы думаете, GCC это программа для людей или нет? =)
Re[2]: Тест по базовому C++ -- интересно ваше мнение
Да, я имею обыкновение выкладывать свои материалы здесь. И что? Хороший форум, всегда можно услышать много интересного =))
VTT>Да, и почему вы выделяете ООП как фичу С++?
Не выделяю. Но им никто никогда не читал ООП. Вот я и начну. Но сначала заполировать то C-подмножество которое они уже знают, научить использовать enum и const, шаблоны и inline, отучить от препроцессора -- полезная грунтовка холста.
Re[3]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Tilir, Вы писали: T>Мне просто интересно, как вы думаете, GCC это программа для людей или нет? =)
Ну, вы не совсем корректно ставите вопрос. GCC (если вы по GNU-компилятор) — это очень сложное, долго эволюционирующее приложение, в котором, наверняка, есть и более ужасные извраты, нежели те, что вы привели. И, думаю, часть из них даже оправдана — или вопросами производительности, или необходимостью поддержки старого кода. Но зачем это студентам? Я сомневаюсь, что даже специалист, вооруженный компилятором, глянув на эту лапшу, сразу сориентируется в происходящем. И я очень надеюсь, что все такие места в промышленном коде будут структурированы и тщательно документированы, мол "мы делаем эту дичь потому-то и потому-то, тут делается то-то, а там — то-то."
Здравствуйте, Tilir, Вы писали:
T>В связи с чем хочу выложить этот тест для местной общественности. Может будут какие-нибудь предложения, замечания, всё такое.
Очень режет глаза "main(void)" — в отличе от Си, в С++ так не пишут.
Также там есть
вот зачем ставить тип возвращаемого значения после template<> ? это не Си где тип результата не входит в сигнатуру функции
1) правильный ответ — "разыменование d — это UB".
Можно сделать каст к [unsigned] char* и разыменовать, но не к short*.
Даже если сделать unsigned char, и d[0] + 256*d[1] + 65786*..., то будет implementation defined, хотя бы изза существования big endian
2) ок
3) не надо учить разбирать такой код, для этого есть http://cdecl.org
достаточно знать что в 1й строчке массив[], а во второй функция()
4) ок
5) тут бы не enum , а enum class
6, 7) зачем этот ад?
8) зачем знать есть ли op< у указателя на функцию, или его нет?
9, 10) в чем смысл этого вопроса? что нельзя слепо кастовать всё подряд? или что массивы не присваиваются?
Вобщем это какой-то очень странный выбор вопросов по "базовому С++". Базовый С++ гораздо больше.
In Zen We Trust
Re[4]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Went, Вы писали:
W> И я очень надеюсь, что все такие места в промышленном коде будут структурированы и тщательно документированы, мол "мы делаем эту дичь потому-то и потому-то, тут делается то-то, а там — то-то."
Знаете, а по жизни в общем всем все равно на что вы надеетесь. В настоящем промышленном коде таких мест куда больше и они куда страшнее и не документировано обычно ничего. Почитайте код qemu, например. Какой-нибудь, скажем, армовский его фронтенд. И не готовить к этому студентов -- преступление перед юношеством. К тому же, конкретно на этот вопрос правильно ответили почти все.
Re[2]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Abyx, Вы писали:
A>вот зачем ставить тип возвращаемого значения после template<> ? это не Си где тип результата не входит в сигнатуру функции
Привычка к гну-стилю и экономия одной строки. Конечно возвращаемый тип надо было перенести на отдельную строчку.
A>1) правильный ответ — "разыменование d — это UB". A>Можно сделать каст к [unsigned] char* и разыменовать, но не к short*.
С чего бы это было UB? Приведение адреса к адресу, типы целочисленные, "An object pointer can be explicitly converted to an object pointer of a different type" (5.2.10-7) и так далее. Мне правда интересно. Я переформулирую вопрос на массивы если это и впрямь так.
A>5) тут бы не enum , а enum class
Там упомянута возможность enum class в одном из аргументов. Увы, штука это пока малоизвестная, в реальной жизни редко встречающаяся, и я решил разобрать лучше просто enum'ы. Возможно тут надо пересмотреть скорее сам курс, чем тест.
A>6, 7) зачем этот ад?
Идея в том, чтобы наглядно продемонстрировать, что препроцессор в этом случае -- плохая замена шаблонам.
A>8) зачем знать есть ли op< у указателя на функцию, или его нет?
Важно понимание что вообще такое указатель на функцию физически и что функции могут как угодно лечь при линковке.
A>9, 10) в чем смысл этого вопроса? что нельзя слепо кастовать всё подряд? или что массивы не присваиваются?
В том чтобы понять разницу вывода типов auto и decltype.
Re[5]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Tilir, Вы писали: T>Знаете, а по жизни в общем всем все равно на что вы надеетесь. В настоящем промышленном коде таких мест куда больше и они куда страшнее и не документировано обычно ничего. Почитайте код qemu, например. Какой-нибудь, скажем, армовский его фронтенд. И не готовить к этому студентов -- преступление перед юношеством. К тому же, конкретно на этот вопрос правильно ответили почти все.
Да, такие вещи бывают, я не спорю. Но тогда вам следовало назвать курс "чтение устаревшего С/С++ кода без использования компилятора", а уж никак не "базовый С++". Но это мое мнение, вы его просили — вы его получили
Re[3]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Tilir, Вы писали:
A>>1) правильный ответ — "разыменование d — это UB". A>>Можно сделать каст к [unsigned] char* и разыменовать, но не к short*.
T>С чего бы это было UB? Приведение адреса к адресу, типы целочисленные, "An object pointer can be explicitly converted to an object pointer of a different type" (5.2.10-7) и так далее. Мне правда интересно. Я переформулирую вопрос на массивы если это и впрямь так.
потому что это нарушает правила aliasing'а.
В стандарте С++ это есть в [basic.lval] p10 > If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined: > — the dynamic type of the object, > ... > — a char or unsigned char type.
И внизу сноска > *) The intent of this list is to specify those circumstances in which an object may or may not be aliased.
То есть конечно кастовать можно в любой тип. Но обращаться к члену нельзя (в вычисляемом контексте).
Ну и это не снимает проблему с implementation-defined представлением int.
Здравствуйте, Tilir, Вы писали:
A>>9, 10) в чем смысл этого вопроса? что нельзя слепо кастовать всё подряд? или что массивы не присваиваются?
T>В том чтобы понять разницу вывода типов auto и decltype.
э? но в чем там разница?
decltype("Apple") a = "Apple"; // const char a[6] = "Apple";
swap(a, p); // вызывается void swap(const char (&t)[6], const char (&u)[5])
auto tmp = t; // const char* tmp = t; // происходит двойное преобразование T(&)[] -> T[] -> T*
t = (T) u; // t = (const char[5]) u;
тут я уже не знаю что будет, никогда так не делал. наверное каст не скомпилируется
Здравствуйте, Tilir, Вы писали:
T>Hi,
T>Продолжаю в свободное от работы время немножко преподавать.
T>Студенты написали (и довольно неплохо) первый в этом году тест, после шести первых лекций, посвященных базовому C++ (всё что можно рассказать человеку со знанием C, не рассказывая ничего про ООП -- включая простые шаблоны функций и decltype/auto).
T>В связи с чем хочу выложить этот тест для местной общественности. Может будут какие-нибудь предложения, замечания, всё такое.
T>--- T>With best regards, Konstantin
Что пользователи этого форума могут сделать, чтобы спасти студентов? Вообще говоря, первые два задания могут сильно деморализовать.
А если серьезно, то недостаточно информации. С одной стороны тест несложный, но с другой стороны это может быть кошмар.
Не зная деталей и рассчитывая на самое худшее, я бы сказал так:
Этот тест вместе с вариантами ответов можно показывать и как учебный материал, а не давать как тест. Видите, дорогие студенты, сколько тут вопросов сложных появляется, значит это говнокод, и так писать не надо. Скорее надо поднять вопрос о том где взять ресурсы, чтобы это исправить и как впредь такого в проекте не допускать.
Для контроля знаний и чтобы показать, что стандарт и всякие толстые книги типа Страуструпа не так уж и страшны, лучше дать каждому по более-менее реальной задачке и потом побеседовать по коду, что там не так или так, провести ревью, показать куда копать с примерами ссылок (на стандарт, а так же на что-нибудь интересное, например, http://www.viva64.com/) и попросить улучшить. Скорее всего, это легче сделать в формате семинаров.
Если же это сродни абсрактному чтению Страуструпа (там тоже в конце каждой главы списочек занимательных вопросов), то это кошмар. Немного попрактиковавшись под руководством хорошего программиста любой нормальный человек и вопросы такие не придумает.
На всякий случай добавлю, что, судя по содержимому вопроса, это не какая-то кафедра компиляторов С++, а обычный курс базовых знаний. Так и надо учить базовым знаниям, надо, чтобы студент почувствовал, что он может этим пользоваться, чтобы он себя комфортно чувствовал в случае возникновения вопросов, чтобы у него пробудился интерес. На рабочем месте, по поводу сомнительного кода, скорее всего, можно будет опять же проконсультироваться с литературой, так что такой тест можно и домой дать.
Так же боюсь, что все просто всё забудут через пару лет. Те, кто не работает на С++ просто забудут, а те, кто работает все равно полезут проконсультироваться со стандратом и т.п.
Ну и на последок, а вообще говоря, есть ли тут правильные ответы, и если есть, то сколько их? Во-первых, существуют разные стандарты C++, разные компиляторы, которые как правило отдельно оговаривают некоторые подобные случаи, об этом ничего не сказано в задании. Во-вторых, существуют разные стандарты по качеству и оформлению кода, там тоже всякое бывает.
Re[2]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, sergz, Вы писали:
S>Для контроля знаний и чтобы показать, что стандарт и всякие толстые книги типа Страуструпа не так уж и страшны, лучше дать каждому по более-менее реальной задачке и потом побеседовать по коду, что там не так или так, провести ревью, показать куда копать с примерами ссылок
Это называется домашняя работа и она тоже есть. Но контроль знаний она не обеспечивает. Я всё-таки преподаю язык а не программирование. Разница -- примерно как между изучением русского языка и русской литературы. Вас же не смущают тесты по русскому языку со всякой упоротой расстановкой запятых и странным написанием гласных/согласных в неожиданных местах ( пример: http://www.examen.ru/add/tests/test )? Ну вот и это такой тест, только по С++.
S>Ну и на последок, а вообще говоря, есть ли тут правильные ответы, и если есть, то сколько их?
Вот это уже может быть началом интересной беседы. Например ув. Abyx высказал серьёзную правку по Q1, где оказывается (возможно) притаилось UB, которого я не заметил, поскольку по новому стандарту сделали более строгие требования к strict aliasing. Отличное замечание и я конечно поправлю тест, чтобы это убрать. Но так вообще я старался тщательно использовать нормативные документы при составлении вопросов и ответов. Так что если что заметили -- то смело говорите =)
Re[4]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Abyx, Вы писали:
A>потому что это нарушает правила aliasing'а.
Очень интересно, спасибо. Я всегда думал о SA как о способе дать понять, что существенно разные типы (такие как int и float) не могут алиасится указателем, что позволяет компилятору двигать код вокруг таких обращений, но не int и short же. Боюсь такое ужесточение делает UB из половины работающего в этом мире кода, но ок, учту.
Re[4]: Тест по базовому C++ -- интересно ваше мнение
Здравствуйте, Abyx, Вы писали:
A>э? но в чем там разница? A>decltype("Apple") a = "Apple"; // const char a[6] = "Apple";
Да, и поэтому Q10 даже не скомпилируется. Но при этом если бы там стояло
auto a = "Apple"; // const char *a = "Apple";
и то же для Pear, то ошибки бы не было. К ошибке компиляции тут приводит именно то, что decltype старается точно сохранить тип, а типы const char[6] и const char[5] не приводимы друг к другу.
Re: тестировать надо с помощью acm.mipt.ru/judge или им подобном
Здравствуйте, Tilir, Вы писали:
T>Hi,
T>Продолжаю в свободное от работы время немножко преподавать.
T>Студенты написали (и довольно неплохо) первый в этом году тест, после шести первых лекций, посвященных базовому C++ (всё что можно рассказать человеку со знанием C, не рассказывая ничего про ООП -- включая простые шаблоны функций и decltype/auto).
T>В связи с чем хочу выложить этот тест для местной общественности. Может будут какие-нибудь предложения, замечания, всё такое.
T>--- T>With best regards, Konstantin