LINUX.ORG.RU

Книга для начинающих программистов, ориентированная на Linux

 , ,


19

5

На сайте А.В.Столярова продолжается сбор средств на написание и последующее издание книги «Программирование: введение в профессию».

Автор проекта уже известен публике по своим книгам Программирование на языке ассемблера NASM для ОС Unix, Сверстай диплом красиво: LaTeX за три дня и другими. Электронные версии всех своих книг автор сразу после выхода бумажного издания выкладывает на сайт, считая это принципиальной позицией.

Книга, задуманная Столяровым в этот раз, должна стать руководством для начинающих, ориентированным на *nix-системы (с использованием командной строки в качестве основополагающего принципа при обучении) и покрывающим при этом предмет от нулевого уровня (школьной информатики) до ООП и парадигм программирования; структура книги приблизительно соответствует последовательности программистских курсов на факультете ВМК МГУ, но отличается от программы ВМК наличием общей платформы (*nix), полным исключением заведомо мёртвых инструментов вроде всё ещё применяющихся на ВМК Турбо-Паскаля и ассемблера MASM для MSDOS, а также существенно иначе расставленными акцентами. Примерный план книги представлен здесь, а с оглавлением неоконченной рукописи, уже включающей три части из предполагающихся семи или восьми — здесь.

Книга отличается от предыдущих своим масштабом. Как было сказано в анонсе проекта,

До сей поры я всегда обходился своими силами; задумав книгу, я просто садился и писал её... Всё было хорошо, пока мои задумки не отличались масштабностью; мне всегда удавалось выкроить пару более-менее свободных недель, чтобы написать текст, и десять-пятнадцать тысяч рублей, чтобы издать написанную книжку. Но в этот раз реальность несколько отличается. Задуманная мною книга по своему объёму по меньшей мере в семь-восемь раз превосходит самые большие тексты, которые мне приходилось писать до сих пор

Даже без дополнительных глав ожидаемый объём книги составляет порядка 1000 страниц; автор планирует уложиться в 500 рабочих часов, для выделения которых необходимо на некоторое время отказаться от подработок. Кроме того, издание книги в бумаге потребует серьёзных расходов, а сотрудничество с издателями на их условиях означало бы невозможность распространения (по крайней мере, открытого) её электронной версии. Автор предпочёл объявить о сборе средств.

К настоящему моменту завершены три из четырёх частей, которые предполагалось написать с нуля; автор продолжает работу над последней из этих частей, посвящённой начальным навыкам программирования (с использованием Free Pascal в качестве учебного пособия); кроме того, в книгу должен после переработки войти материал из пособий, изданных ранее, образовав оставшиеся четыре части. Поддержать проект можно здесь; для доноров предусмотрены разнообразные плюшки.

>>> Подробности

★★★

Проверено: maxcom ()
Последнее исправление: CYB3R (всего исправлений: 2)
Ответ на: комментарий от anonymous

Чел, который не понимает что такое циклы/рекурсия/условный оператор/пузырек вылетает,

Так что бы их понять, а не заучивать наизусть и нужна практика, на реальных машинах, а не на бумаге.

drfaust ★★★★★
()
Ответ на: комментарий от anonymous

Ну дык и я о том же писал. Но нашим учителям не прикажешь, какую программу пропихнули тому и пытаются учить.

drfaust ★★★★★
()
Ответ на: комментарий от Croco

уже существующая книга по NASM,

А может стоило хотя бы один параграф посвятить сравнению с fasm? Просто перечислить все отличия на уровне самого языка, хотя бы может и не касаясь макросов, чтобы все примеры можно было сразу и в fasm использовать?

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

А может стоило хотя бы один параграф посвятить сравнению с fasm?

Гм, ну вот мне теперь ещё fasm изучать. Вообще-то я могу и изучить, это несложно, только зачем? Всерьёз программировать на ассемблерах никто ничего не станет, жизнь коротка; в процессе обучения ассемблер нужен, чтобы понять Суть Вещей, причём для большинства программистов период начального обучения — это единственный шанс получить хоть какой-то опыт работы на асме; без такого опыта программирование становится похоже на шаманство, но, приступив к профессиональной работе, человек уже в большинстве случаев никогда не найдёт в жизни лишней пары недель, чтобы посвятить их какому-нибудь этюду на асме. Поэтому это обязательно надо делать в процессе обучения, пока ещё запал не прошел.

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

Croco ★★★
() автор топика
Ответ на: комментарий от Croco

[code] char buf[20];

scanf(«%19s», buf);

Ага (в смысле, переполнения не будет), только в отличие от printf это вот 19 в scanf'е почему-то нельзя взять из параметров. Следовательно, нельзя привязать к тем 20. Уволить не уволят, но публичную порку устроят.

А в scanf разве нельзя подсунуть что-то вроде этого:

int buf_size = 20;
char *buf = malloc(buf_size);
char format_string[32];
sprintf(*format_string, "%%%ds", buf_size-1);
scanf(format_string, buf);


Давно на C не писал, мог что-то напутать, плюс нет проверок на успешность маллока и тд, но как-то так.

Xenius ★★★★★
()
Последнее исправление: Xenius (всего исправлений: 2)
Ответ на: комментарий от Croco

Тогда fasm лучше тем, что сам написан на себе, то есть сам является примером, ещё там макроязык вроде как помощнее (не знаю на самом деле), но хуже тем что не портируемый на другие архитектуры (например на ARM-машине не запустить его без эмулятора) и не поддерживает некоторые форматы объектых файлов / дебаг информации. Думаю для обучения он может быть всё-таки лучше так как там можно например самому формировать весь бинарный файл с нуля и не требуется отдельный линкер.

Зачем? Ну во-первых для кругозора, во-вторых для улучшения книги. Ещё неплохо бы дать список литературы — ну где брать спеки на i386 и так далее.

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

А в scanf разве нельзя подсунуть что-то вроде этого:

Конечно, можно. Вообще любую проблему решить можно, можно даже навесить какой-нибудь дополнительный внешний препроцессор, который что-то такое сделает с нужными форматными строками. Если проблема алгоритмически разрешима, то справиться с ней можно; даже если неразрешима, всё равно в большинстве случаев что-то можно придумать.

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

Суть в том, что для таких вещей есть более, скажем так, общепринятое решение: читать посимвольно. Оно и для восприятия проще, и универсальнее (вам ведь всё равно придётся как-то обрабатывать случай «не влезло», так что химией с форматными строками дело не кончится), и работает быстрее.

Croco ★★★
() автор топика
Ответ на: комментарий от IvanR

for (i = 0; i < 24 / sizeof(int); i++) {

А не (24 / sizeof(int) + 1)? Представим что там было 1, а не 24, тогда 1/2 даст 0, а тебе нужно 1, так как одно число в массиве есть.

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

ещё там макроязык вроде как помощнее (не знаю на самом деле)

Я как-то на нём CRC32 от строки считал, так что очень даже мощный.

mix_mix ★★★★★
()
Ответ на: комментарий от Croco

Вот тут у вас в рантайме генерируется строка, при том что её содержание заведомо известно во время написания. А вы в рантайме время тратите.

Вообще, не совсем. Я специально написал malloc, чтобы длина строки задавалась тоже в рантайме. У меня там int buf_size = 20;, но на самом деле buf_size мог бы получаться из параметров командной строки или ввода, так что без рантайма не обойтись, хотя это и извращение конечно. А если всё-таки делать фиксировано, то лучше было бы взять #define BUF_SIZE 20 и тогда бы её вроде как можно было задать и в scanf

вам ведь всё равно придётся как-то обрабатывать случай «не влезло», так что химией с форматными строками дело не кончится

Я на втором курсе думал, что знаю C, теперь я думаю, что не знаю. Конечно написать что-нибудь, что будет работать с какого-то раза я могу, но чтобы оно ещё и правильно работало нужно знать слишком много тонкостей. По-моему было бы проще взять какой-нибудь другой язык, а не C, чем эти тонкости изучать. Кстати я не знаю, где про них можно прочитать в централизованном виде.

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

там можно например самому формировать весь бинарный файл с нуля и не требуется отдельный линкер.

вроде в любом асме можно, главное - структуру знать. в fasm'e для этого есть директивы.

Deleted
()
Ответ на: комментарий от Xenius

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

Проблема в том, что Си в некоторых областях не имеет альтернатив, ну то есть можно на асме писать (но жизнь коротка), а если не на асме - то остаётся только Си. Больше ничего просто нету. Вот и использует весь мир эту откровенную коленно-гаражную поделку.

Тем удивительнее, что всё новое, что появляется, просто-таки изначально делается так, чтобы даже близко не иметь никаких шансов заменить Си.

Croco ★★★
() автор топика
Ответ на: комментарий от Deleted

с модулой и обероном не имели дела?

С модулой — нет, не имел. Насчёт Оберона — Чернов вон оберонистов сектой назвал, и чем дальше, тем больше я с ним согласен. В роли учебного языка (для замены Паскаля) Оберон не подходит из-за сборки мусора. К тому же нормальной реализации нет (пардон, бинарник компилятора под винду, от которого даже исходников нет — это не реализация, это недоразумение). Судя по всему, Оберон как реальный язык программирования не существует и никогда не существовал.

Croco ★★★
() автор топика
Ответ на: комментарий от Croco

Чернов

а кто это?

Про оберон да, забыл о gc. Чем плох тот же паскаль, как замена си, или модула (кстати для gcc есть фронтенд)?

Deleted
()
Ответ на: комментарий от Deleted

Чернов — мой коллега по работе, достаточно известный человек. Автор ejudge, например.

Чем плох тот же паскаль, как замена си,

У Си есть такое интересное свойство - Zero Runtime. То есть можно отказаться от библиотечной обвески, точно зная, что компилятор ничего самовольно в объектный код не втащит. Это позволяет на Си писать такие вещи, как ядра операционных систем, бут-секторы всякие, прошивки для микроконтроллеров и прочие программы, не предполагающие наличия вокруг них операционки. Больше никакой язык для этого не годится.

Croco ★★★
() автор топика
Ответ на: комментарий от Croco

На плюсах тоже можно (при определенных условиях).

У раста в принципе тоже зеро рантайм (сборщика мусора и подобного в том числе нет), но есть проблемы с запиливанием своих менеджеров памяти, которые могут иметь дело с ситуацией, когда память закончилась. Если допилят в этом направлении, то будет очень ок, в том числе и для голого железа (хотя и так умельцы на нем систему писали простенькую, например, https://github.com/scialex/reenix).

anonymous
()
Ответ на: комментарий от anonymous

А, ну и, естественно, раст пока сильно экспериментален. Так что для обучения (начального) или продакшена — пока вообще никак.

Плюсы для совсем начального обучения все-таки не ок. Как, впрочем и Си с растом.

anonymous
()
Ответ на: комментарий от Manhunt

Раскройте, в чем калечество? Паскаль как паскаль. Если мы вначале классическую императивщину с переходом на низкий уровень хотим. Если вначале какую лиспятину, то схем ок. Но все равно низкий уровень надо изучить.

anonymous
()
Ответ на: комментарий от anonymous

Раскройте, в чем калечество?

Калечество — в неспособности обойтись в учебной программе без языков, которые были актуальны лет 30 назад, а сейчас не примечательны ничем, кроме замшелых преподавательских привычек.

Если требуется показать «низкий уровень», то нужно показывать его вместе с Си: основные ОС и драйвера к ним написаны на Си, микроконтроллеры программируются в основном на Си; поэтому без Си адекватного введения в низкоуровневое программирование не получится. И если уж собрался давать Си, то глупо распыляться на Паскаль.

Если «низкий уровень» показывать не требуется, то, опять же, есть подходящие для преподавания и гораздо более актуальные чем Паскаль языки. Тот же Питон.

Итого, Паскаль — это в чистом виде лишняя сущность.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от anonymous

У раста в принципе тоже зеро рантайм

Не совсем, точнее, как я понял (увы, в данном случае с чужих слов), совсем не. Сам я тут не вполне владею темой, не было пока времени Rust смотреть внимательнее, но один мой аспирант, предприняв в этом направлении исследование на тему, не годится ли Rust как замена Си, в итоге сказал, что там имеются (на уровне языка) конструкции, реализация которых настолько нетривиальна, что заведомо потребует поддержки в виде «невидимых» функций, а это и есть, собственно говоря, runtime. Си — это такой «почти ассемблер», любая конструкция Си в машинный код преобразуется способом очевидным и предсказуемым, и не требует «невидимых» подпрограмм.

Croco ★★★
() автор топика
Ответ на: комментарий от Manhunt

И если уж собрался давать Си, то глупо распыляться на Паскаль.

Слушай, гений ты наш методический, ты мне надоел. Научи чему-нибудь хотя бы десятую часть того количества людей, которых я чему-то научил, потом поговорим.

Я-то этому Си — в том числе и в качестве первого в жизни языка, в том числе и на частных уроках — обучил уже не одну сотню людей, да и не две, учитывая, что веду занятия на втором курсе ВМК, где как раз Си изучается, и делаю это ежегодно с 2000 года, обычно две группы каждый год, вот и считай. Сдаётся мне, я знаю, что тут глупо, а что нет. На собственной буквально шкуре.

Croco ★★★
() автор топика
Ответ на: комментарий от anonymous

На плюсах тоже можно (при определенных условиях).

Ну да, если отключить RTTI и exceptions. Виртуальность вроде за собой ничего не тянет, а вот реализация исключений — это адский ад.

Croco ★★★
() автор топика
Ответ на: комментарий от Croco

гений ты наш методический

И давно отказ от откровенного убожества стал приравниваться к гениальности?

Я-то этому Си ... на втором курсе ВМК

Ещё разок: зайди на соседний факультет, и посмотри, как Си дают в первом семестре программирования, безо всякой паскалятины, и без особых затруднений.

Или, как вариант, попробуй найти методическое место своего паскаля в программе MIT.

Сдаётся мне, я знаю, что тут глупо, а что нет.

А мне сдаётся, что твой подход был бы нормален для учебного заведения третьего эшелона. Скажем, для какого-нибудь заборостроительного колледжа. А для титульного ВУЗ-а страны, это ужасно стыдно.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 2)
Ответ на: комментарий от anonymous

так я что-то не понял: это для вузов учебник или для начинающих с самого нуля?

«структура книги приблизительно соответствует последовательности программистских курсов на факультете ВМК МГУ» (с) ТС

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

паскаль же школьный, нам давали после васика

anonymous
()

А всё же до чего приятно читать коменты хейтеров при уровне аргументации «в Англии ружья кирпичем не чистят!» Деградация отечественного ИТ проявляется на ЛОРе во всей красе. Автору - удачи! Пока остальные критикуют - кто-то должен и делать!

anonymous
()

Андрей Викторович, подскажите пожалуйста, на каком факультете в МГУ преподают биоинформатику и программирование на суперкомпьютерах?

anonymous
()
Ответ на: комментарий от anonymous

Суперкомпьютеры идёшь на пятый этаж и ищешь кафедру ски. Про биоинфу идёшь на факультет биоинфы. Если ты под биоинфой понимаешь генетику, идёшь в 762.(спецсем кафедры ски)

anonymous
()
Ответ на: комментарий от Croco

Тем удивительнее, что всё новое, что появляется, просто-таки изначально делается так, чтобы даже близко не иметь никаких шансов заменить Си.

C слишком широко распространён, так что каким бы хорошим это что-то новое ни было, шансов у него немного.

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

если внимательно взглянуть на код, то в моем ошибки нет, там массив не весь алфавит, а округлен до числа, кратного четырем в меньшую сторону, а вот ваш код как раз приведет к undefined behavior, поскольку копируем мы не побайтно, а по sizeof(int) байта за одну итерацию, ваш код загадит память случайными данными за пределами целевого массива.

IvanR ★★★
()
Ответ на: комментарий от Xenius

ну там разговор был об понимании адресной арифметики, и потом так быстрее, чем побайтно, хотя может быть memcpy еще быстрее, но надо смотреть реализацию, для уверенности.

IvanR ★★★
()
Ответ на: комментарий от Croco

Оберон не подходит из-за сборки мусора. К тому же нормальной реализации нет (пардон, бинарник компилятора под винду, от которого даже исходников нет — это не реализация, это недоразумение). Судя по всему, Оберон как реальный язык программирования не существует и никогда не существовал.

Язык Оберон интересен не сам по себе, а как часть учебного «проекта Оберон», особенно в «редакции 2013-го года» (хотя в исходниках встречаются комментарии о правках и за конец 2014-го): небольшим объемом кода описывается компьютер (на Verilog), компилятор (на Oberon), операционная система (на Oberon), графическое пользовательское окружение (на Oberon). Всё вместе - меньше 500 KB исходников. И всё это запускается на FPGA-плате с подключенными VGA-монитором (туда выдается 1024x768x1-bit), клавиатурой, мышкой, и, похоже, опционально модулем nRF24L01+ для беспроводной связи между такими компьютерами (есть код на Обероне от интерфейса с этим модулем до подпрограмм приема/передачи файлов, но, похоже, нет к нему готового пользовательского приложения?)

http://www.projectoberon.com
http://www.inf.ethz.ch/personal/wirth/ProjectOberon/
http://issuu.com/xcelljournal/docs/xcell_journal_issue_91/30

Исходники компилятора там дают в or.zip, написан на Обероне же (что и хорошо и плохо), около 3000 строк (120 KB).

Разве что исходников начального загрузчика (стр. 12 в PO.Computer.pdf) я не вижу. Он дается в виде prom.mem в RISC5Verilog.zip, там 512 слов, из них 376 ненулевые. Но я не исключаю, что исходников и не было - такой объем не сложно и прямо в кодах написать. ;-) Да, и шрифты в бинарных файлах - опять же, не ясно были ли они когда-либо в другом формате или это исходный.

Зато книга в свободном доступе. (Кстати, в тему этого треда.)

solardiz
()
Ответ на: комментарий от Croco

Croco, рад тебя здесь видеть. Удачи с проектом! Но я всё же придерусь (может быть, это поможет твоей книге):

Си — это такой «почти ассемблер»

Я тоже когда-то так думал.

Я не уверен как лучше, но моё нынешнее мнение, что при обучении преподносить Си как «почти ассемблер» не указав в ту же минуту на огромную неточность этого утверждения — опасно. Не уверен, что его вообще следует подавать в таком ключе.

Да, Си позволяет делать много чего как-бы низкоуровневого и не требует runtime'а, но, в отличие от ассемблера, не описывает ни последовательность действий (за исключением sequence points, да и то при условии отсутствия в программе undefined behavior), ни точное расположение данных в памяти (за некоторыми исключениями вроде адресации через «volatile unsigned char *ptr = 0;»), даже относительное (кроме элементов массивов и полей упакованных структур, но и с ними без volatile компилятор не обязан делать чтения/записи из/в память, а может, например, кешировать в регистрах, а память под них и не выделять вовсе). К этому добавляется огромное количество возможных случаев undefined, unspecified, implementation-defined behavior (три разных понятия), причем implementation-defined не гарантирует очевидного соответствия конкретной платформе (железа).

С другой стороны, и ассемблер описывает последовательность действий и расположение данных лишь для конкретной архитектуры, которая сама может быть уровнем абстракции над железом. Современные (и не очень) процессоры, как правило, гарантируют лишь сохранение семантики (причем конкретные гарантии, в особенности в отношении разделяемой памяти, отличаются между архитектурами), а не последовательность действий и не расположение данных. На практике, инструкции могут быть разбиты на части (например, загрузка данных и вычислительная операция), склеены вместе (например, проверка и условный переход), переставлены местами по частям или целиком, заменены другими действиями или опущены (например, переименование регистра вместо присвоения значения), а данные могут оставаться в кеше или/и в каком-либо буфере или bypass'е. Так что с этой точки зрения аналогия с Си есть, но наборы гарантий по сохранению семантики сильно отличаются.

любая конструкция Си в машинный код преобразуется способом очевидным и предсказуемым, и не требует «невидимых» подпрограмм.

Может быть преобразована очевидным и предсказуемым образом, а может и вовсе нет. Строго не требует «невидимых» подпрограмм, но может быть откомпилирована в код, их использующий (например, если программа использует операцию деления, а архитектура такой инструкции не имеет). Си просто не дает таких гарантий. Конкретный компилятор с конкретными опциями может их давать, но это относится и к компиляторам с других языков.

Если считать Си аналогом ассемблера, можно было бы ожидать, в частности, повторения особенностей семантики соответствующих инструкций целевой архитектуры. Но нет:

$ cat s.c
#include <stdint.h>
#include <stdio.h>

static uint32_t shift(uint32_t x, uint32_t s)
{
        return x >> s;
}

int main(void)
{
        printf("%x\n", shift(0x98765432, (uint32_t)-1));
        return 0;
}
$ gcc s.c -o s -O0 -s -Wall; ./s
1
$ gcc s.c -o s -O2 -s -Wall; ./s
30eca864
$ uname -ms; gcc --version | head -1
Linux i686
gcc (GCC) 4.6.3

На практике, одна из самых коварных особенностей Си — strict aliasing. В этом треде уже был пример копирования строк через «int *». Конкретно этот пример даже корректный, т.к. в нем второй тип «char *», который может alias'ить любой другой тип. Но вот был бы аналогичный код в функции my_memcpy(), и вызвали бы ее, скажем, с аргументом типа «uint64_t *» (с соответствующим cast'ом, или функция принимала бы «void *») — и у нас проблема. Программа, при отсутствии в ней других проблем, скорее всего, будет собираться без предупреждений и даже правильно работать на конкретной системе. (Я предполагаю, что общий размер копирования правильный, а выравнивание достаточное. Это отдельные темы, которые были бы и в ассемблере.) Но у кого-то сломается при сборке более агрессивным компилятором (function inlining, особенно в сочетании с LTO). Кстати, временное преобразование через безопасные «char *» или «void *», как было бы в вызове my_memcpy(), гарантий не дает (и проблема зачастую всё равно вылезает при включении function inlining, что дает возможность компилятору «увидеть» разные небезопасные типы). Большинство нетривиальных программ на Си имеют нарушения strict aliasing. Многие уже проявились, многие ждут своего времени проявиться.

Я согласен, что распространенной альтернативы Си пока нет, и даже на недостатках(?) Си можно учиться, если акцентировать на них внимание и объяснять как мы до такого дошли (в примере выше: желание не отставать в производительности генерируемого кода от Фортрана). Так что я не к тому, чтобы не преподавать Си, но к тому как его преподавать.

solardiz
()
Ответ на: комментарий от Xenius

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

Проще, да. Лучше ли, не знаю.

Кстати я не знаю, где про них можно прочитать в централизованном виде.

Бесплатно:

https://www.securecoding.cert.org/confluence/display/c/SEI CERT C Coding Stan...

Платно (если кто купит, комиссию от Amazon отдам Croco на его книгу):

http://astore.amazon.com/openwallproje-20/detail/0321444426

«The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities», глава 6 «C language issues» (вроде бы, 94 страницы эта глава, 1200 страниц вся книга).

На русском — не знаю.

solardiz
()
Ответ на: комментарий от Croco

char buf[20];
scanf(«%19s», buf);

Ага (в смысле, переполнения не будет), только в отличие от printf это >вот 19 в scanf'е почему-то нельзя взять из параметров. Следовательно, >нельзя привязать к тем 20. Уволить не уволят, но публичную порку >устроят.

А макросом?Формировать «%19s» из (sizeof(buf)-1)

anonymous
()
Ответ на: комментарий от solardiz

shift(0x98765432, (uint32_t)-1))

Сдвиг на -1, то есть теоретически должно получиться <<1 и 0x30eca864, но учитывая что там не арифметический сдвиг, это на самом деле сдвиг на 2^32-1, который должен давать 0, как и любой сдвиг по модулю больше чем на 32?

Полагаю, тут проблема в кривых конечностях программиста, который использует шифт с заведомо неправильным аргументом и преобразование из signed в unsigned. Кажется в C был >>> который нужно использовать.

и вызвали бы ее, скажем, с аргументом типа «uint64_t *»

Не совсем понял, что ты имеешь ввиду. Если бы он копировал кусками по 8 байт, были бы проблемы? Почему?

Проще, да. Лучше ли, не знаю.

Конечно лучше. Если надо очень быстро — макроассемблер, если не обязательно — да хотя бы Lua.

комиссию от Amazon отдам Croco на его книгу

Какую комиссию? Ты автор что ли?

Xenius ★★★★★
()
Ответ на: комментарий от solardiz

на недостатках(?) Си можно учиться, если акцентировать на них внимание

Мне кажется, что при введении в программирование убогость и костыльность Си нужно элегантно обходить сторонкой. Собственно, как это и делается при написании хорошего продакшн кода.

А «срыв покровов» про внезапные UB, про sequence points и прочие контр-интуитивные грабли — это предмет отдельного, углубенного курса.

Manhunt ★★★★★
()
Ответ на: комментарий от Xenius

теоретически должно получиться [...] должен давать

В том-то и дело, что в Си это UB, так что ничего конкретного происходить не должно. Корректный компилятор, теоретически, может даже system(«rm -rf /») вызвать. «If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.»

Полагаю, тут проблема в кривых конечностях программиста, который использует шифт с заведомо неправильным аргументом

Конечно, но «заведомо» неправильность очевидна лишь в таких простых примерах и для того кто знает что это UB. А вот вычислялся бы сдвиг на основе каких-то параметров, приходящих из другой части программы, и возможен ли UB в этом месте было бы уже не очевидно даже знающему от том что такое бывает. Пример не надуманный — эта проблема проявилась в Pufferfish, одном из алгоритмов хеширования паролей, поданном на конкурс PHC. Автор Pufferfish, вероятно, проверил как себя ведет сдвиг вправо на отрицательную величину в тестовой программе. И решил, что такое же поведение будет сохраняться и в контексте кода Pufferfish, причем для всех его сборок. Реально же вышло, что поведение Pufferfish при запрошенном объеме памяти более 2 MiB не определено, вопреки желанию автора.

преобразование из signed в unsigned.

Это я лишь для наглядности в конкретном примере, но, возможно, зря, т.к. оно же и отвлекает внимание. Такое преобразование определено: «if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.» Так что это то же самое, что 0xffffffffU.

Кажется в C был >>> который нужно использовать.

Не слышал о таком. В псевдо-коде, >>> и <<< часто используют для обозначения циклического сдвига, но в Си этого нет.

Не совсем понял, что ты имеешь ввиду.

Видимо, ты не в курсе про strict aliasing.

Если бы он копировал кусками по 8 байт, были бы проблемы? Почему?

Нет, дело не в размере кусков, а в нарушении правил aliasing'а. Предполагается, что программист заключил с компилятором неявный контракт, что, за некоторыми исключениями, указатели на типы данных разных размеров не могут указывать на одни и те же или пересекающиеся данные. Нарушение может караться хоть тем же system(«rm -rf /»), но на практике часто карается перестановкой операций местами так, что логика программы перестает соответствовать ожиданиям программиста, или выкидыванием фрагментов кода рядом с этим нарушением (всё равно undefined, так что какая разница, можно его и «оптимизировать»). Есть и явный аналог этого контракта — слово restrict, позволяющее расширить контракт и на случай совпадения размеров.

Конечно лучше. Если надо очень быстро — макроассемблер, если не обязательно — да хотя бы Lua.

Мы об обучении, а не о конкретной разработке.

Что касается ассемблера «если надо очень быстро» (чтобы код работал быстро?), то при современных компиляторах и сложности микроархитектуры процессоров, производительность кода, до особых усилий по оптимизации (или сразу примененных знаний, если есть), зачастую получается ниже, чем у выдачи оптимизирующего компилятора Си.

Какую комиссию? Ты автор что ли?

Нет. Это affiliate-ссылка. Amazon платит, хоть и «копейки» (так мало, что с точки зрения заработка на этом это, как правило, не стоит времени даже на регистрацию у них аккаунта). Просто раз уж исходно тема была сбора средств.

solardiz
()

Здравствуйте!

Вот одна из неплохих книг, на мой взгляд:

Арнольд Роббинс «Linux.Программирование в примерах.».

Изд-во КУДИЦ-ОБРАЗ Москва 2005

Al1234567
()

Так когда будет готово?

anonymous
()
Ответ на: комментарий от Manhunt

Мне кажется, что при введении в программирование убогость и костыльность Си нужно элегантно обходить сторонкой. Собственно, как это и делается при написании хорошего продакшн кода.

а потом в резюме появляется незатейливое «знаю си» у людей, даже близко не понимающих, что такое си

или еще хуже: C/C++

unt1tled ★★★★
()
Ответ на: комментарий от unt1tled

в резюме появляется незатейливое «знаю си»

А вакансиях появляется такое же незатейливое «опыт разработки от 3х лет». Если человек за 3 года не уловил, что си не так прост, и не постарался с ним разобраться детальнее.. ССЗБ

Manhunt ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.