Вышел первый том

image of the volume1 cover Итак, сегодня, 23 марта 2016 года, я привёз из издательства бумажный тираж первого тома. Как и было обещано, электронная версия тут же сделана доступной на сайте; «официальная» ссылка на PDF-файл расположена на страничке, посвящённой первому тому, но для нетерпеливых привожу ссылку прямо здесь: http://www.stolyarov.info/books/pdf/progintro_vol1.pdf

О материальных плюшках и прочем — чуть позже (видимо, завтра) отдельной новостью, дайте дух перевести :-)

опечатки?

- стр.128: "...шестнадцатеричные цифры, получим 217A..." (возможно, "217B");
- повтор: чтобы найти комментарии к первому тому, нужно искать через публикации на стр. 8 (комментарии не прикручены к странице первого тома, а к остальным томам прикручены);

admin аватар

Опечатка

Опечатка известна, да.

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

опечатка?

- стр. 331: "...программа перед завершением устанавливает...темно-серый цвет текста;...", а в коде TextColor(LightGray);

- стр. 328-329: при максимальных значениях star (ScreenWidth, ScreenHeight) наблюдается вывод дополнительных "звездочек". Но это, так, если придираться.

- стр. 97-98:

- стр. 97-98: кириллические символы в скриптах (в примерах оператора ветвления: "Файл file.txt не найден") несколько "режут" глаза.
Спасибо.

admin аватар

Уже замечено и

Уже замечено и в рукописи поправлено, во второе издание не пролезет. Просто этот фрагмент пришёл исходно из этой вот книжки, изданной 11 лет назад, а написанной ещё раньше; тогда я ещё не всё понимал, что надо. А при переносе в новую рукопись уделил внимания этому тексту меньше, чем следовало.

admin аватар

> стр. 331 Спасибо

> стр. 331

Спасибо за внимательность. Это на самом деле опечатка не в тексте, а в примере — в тексте я цвет поправил, в исходнике, который в архиве — тоже, а перенести правку исходника в текст рукописи забыл. В новом издании этот фрагмент в любом случае будет скорректирован -- он будет восстанавливать настройки терминала по умолчанию, выдавая esc-последовательность.

> стр.328-329

Это не дополнительные звёздочки, это старую звёздочку стереть не удаётся, потому что позиционирование для выдачи пробела не проходит. В принципе да, можно, наверное, текст примера скорректировать, чтобы он звёдочку не выпускал в крайние позиции.

восстановление исходных режимов терминала

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

uses
    process;
var
    reset_process: TProcess;
begin
    reset_process := TProcess.Create(nil);
    reset_process.Executable := 'reset';
    reset_process.Options := reset_process.Options + [poWaitOnExit];
    reset_process.Execute;
    reset_process.Free
end.
admin аватар

К сожалению,

К сожалению, для книжки это не годится. Я не показываю в книжке "заклинаний", не объясняя их смысл, а рассказывать в первом томе про процессы — это очевидный перебор.

восстановление исходных режимов терминала

Андрей Викторович, у меня "write(#27'[0m');" перед завершением программы не производит никакого эффекта. Как заставить этот прием заработать? Спасибо

admin аватар

Попробуйте write

Попробуйте write заменить на writeln. Больше ничего в голову не приходит, последовательность стандартна для всех ныне используемых терминалов (точнее, их эмуляторов).

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

Здравствуйте, подскажите, пожалуйста: во фрагменте кода на стр. 376 (удаление элемента с отрицательным значением с помощью указателя на указатель) после dispose(tmp), куда указывает указатель из предыдущего элемента (т.е. тот указатель, который указывал на удаленный элемент)? Корректен ли такой вопрос вообще?
Спасибо.

admin аватар

Рисуйте квадратики :-)

Если вы нарисуете это всё примерно как на рис.2.11, то поймёте, что указатель pp (имеющий тип указатель на указатель) как раз указывает на тот указатель, значение которого вас беспокоит. Следовательно, pp^ -- это как раз и есть тот самый указатель. Строчкой выше (перед dispose) в него заносится адрес следующего элемента списка, взятый из поля next текущего (удаляемого) элемента. После этого в списке уже нет ни одного указателя, указывающего на удаляемый элемент, он доступен только через tmp, так что его удаление никого и ничего нарушит.

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

Здравствуйте, подскажите, пожалуйста, на стр. 376 в цикле используется конструкция:
else
pp := @(pp^^.next)
end
Вопрос: корректна ли замена указанной выше конструкции на фрагмент:
else
pp^ := pp^^.next
end.

Спасибо.

И, возможные опечатки:
стр. 186 - 2й обзац: “...на печать значения байов...”.
стр. 255 - 1й абзай: “...битовая строка 0000...” (15 цифр, а не 16 ?).
стр. 371 - while not eof (а не Seekeof ?).

admin аватар

н-да

Нет, замена абсолютно некорректна. То есть вот совершенно, от слова совсем. И то, и другое откомпилируется, но делают эти два присваивания совершенно разные вещи.

По опечаткам -- "байов" уже заметили раньше, за количество цифр спасибо, их ещё никто не догадался посчитать :) Что до not eof, то в данном случае это будет работать, ведь используется readln. Если предполагать, что файл всегда кончается переводом строки и что в строках нет незначащих пробелов, будет всё правильно.

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

Здравствуйте, подскажите, пожалуйста: на стр. 364 в примерах удаления первого элемента из односвязного списка фрагменты "dispose (first)" и "dispose (tmp)" заявлены как удаление элементов.
Вопрос: данные фрагменты удаляют указатели или элементы, или и первое, и второе? Что будет означать фрагмент "dispose (first^)", удаление первого элемента?
Спасибо.

admin аватар

Я рекомендовал

Я рекомендовал бы вам вернуться на несколько страниц назад и прочитать, что делает dispose. А заодно подумать, о каком вообще "удалении" может идти речь в применении к переменной, имеющей имя (на всякий случай: new и delete работают с динамической памятью, то есть создают и уничтожают такие переменные, у которых имён нет и быть не может).

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

Здравствуйте, подскажите, пожалуйста: в программе Number1 на стр. 363 не вполне понятен фрагмент "tmp =: first; {проходим по списку с начала}". Насколько верна мысль об удалении указанной выше строки, а продолжить так:

...

{цикл чтения чисел}

end;

while first <> nil do begin

writeln(first^.data);

first := first^.next

end;

end.

Спасибо.

admin аватар

В данном

В данном конкретном случае программа будет работать точно так же, как и в примере, поскольку после этого цикла список больше не используется. В реальной ситуации так делать нельзя категорически: сдвигая указатель first, вы теряете (переводите в мусор) элементы списка, т.е. с прагматической точки зрения вы после этого цикла больше не сможете ничего сделать с этим списком, в том числе и удалить его. С идеологической точки зрения всё ещё хуже: когда список надо просто просмотреть, его НЕЛЬЗЯ для этого изменять, такие вещи должны соблюдаться на уровне рефлексов.

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

Здравствуйте. Похоже, что на стр. 253 опечатка: при вызове процедуры PrintDigitsOfNumber(7583) результат - "3857" (а в pdf-версии книги заявлен результат "3875").

admin аватар

вы совершенно правы

что характерно, на эту опечатку никто ещё внимания не обратил. Я её теперь пометил в своём экземпляре, так что в случае переиздания она будет исправлена.

Опечатка

Подобная опечатка, возможно, на стр. 254: "...для того же самого вызова напечатано будет "5 7 8 3"..." (а результат вызова процедуры - "7 5 8 3").
Андрей Викторович, спасибо за Вашу работу.

admin аватар

да, факт

отметил, спасибо

Ошибка при компиляции.

Здравствуйте.
Подскажите, пожалуйста: фрагмент кода на стр. 253 (тема 2.4.5. Рекурсия) в pdf-версии книги не проходит компиляцию с формулировкой "Wrong number of parameters specified for call to "PrintChars"" в строке с PrintChars(count - 1).
Спасибо.

admin аватар

это известная опечатка

там должно быть PrintChars(ch, count-1)

Странный список литературы

Я не специалист в вашей теме (я химией занимаюсь), поэтому ничего не могу сказать по существу содержания книги. Поэтому, прокомментирую лишь список литературы на стр. 458. Во-первых, он очень краткий. В любом книжном магазине есть несколько стеллажей с книгами по компьютерной тематике. Это всё "мусор", среди которого нет ничего заслуживающего чтения и, соответственно, упоминания в списке литературы вашей книги? Во-вторых, самая новая приведённая вами ссылка идёт на книгу 2006 года, т.е. это время Windows XP и первого iPhone. Про ссылку [1] Баурн С. Операционная система UNIX. М. Мир, 1986 я вообще молчу. С тех пор в программировании не появилось ничего нового?

admin аватар

Смешно, да.

> Это всё "мусор", среди которого нет ничего заслуживающего чтения

Процентов на девяносто семь это действительно мусор. Иначе мне не пришлось бы писать свои варианты учебников; каждая из моих книг — результат того, что мне нечего порекомендовать студентам в ответ на вопрос, что почитать по той или иной теме.

> соответственно, упоминания в списке литературы вашей книги?

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

> Windows XP

Начать с того, что системы линейки Windows вообще не имеют права на существование, закончить тем, что XP — это последняя из них, которую можно хоть как-то терпеть. Всё, что M$ родил позже — это системы, каждая из которых представляет собой одного большого трояна.

> первого iPhone

...для iДиотов

> С тех пор в программировании не появилось ничего нового?

С каких "тех", с середины нулевых?! Я вам так скажу, в программировании последнее заслуживающее разговора новшество относится к середине 1970-х, это парадигма объектно-ориентированного программирования. После этого действительно не было ничего нового и при этом такого, что можно было бы назвать прогрессивным. "Новшества" наших дней из области IT — это не прогресс, это маркетоидское мракобесие и примкнувший к нему особый вид международного терроризма, называемый технической стандартизацией.

В общем, похоже, лучше вам дальше химией заниматься. Хорошая наука, полезная.

Пара опечаток

На странице 76 печатной версии вместо (в нашем примере это /home/lizzie), вероятно, должно быть (в нашем примере это /home) -- там речь идет о значении "..".

На странице 92 её же ошибка копипасты: получилось, что 1, и 4 соответствуют правам на чтение. Еще в этой секции вы сразу начинаете разговор с "12-битного слова", притом что раньше, кажется, слово бит в книге ни разу не упоминалось. Может быть, стоит сделать сноску 29 прямо здесь, а не внизу страницы.

Очень может быть, что кто-то опечатки уже заметил, но я об этом не знаю -- почему бы вам не завести специальную страничку на сайте со списком всех известных опечаток?

admin аватар

Спасибо!

Про опечатки -- да, эти уже замечены. но всё равно спасибо :-) Хорошее замечание про слово "бит", этого до вас никто не заметил.

Про список найденных опечаток -- я об этом думал, но сейчас решительно нет на это времени :(

Прочитал Вашу

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

P.S. Но это не важно. Еще раз, спасибо за книгу!

admin аватар

Да ладно, там же просто всё

Три ряда по девять карт, верхний ряд, средний и нижний. И спросить, в каком ряду загаданная карта. Потом этот ряд в колоду кладём в середину, а снизу и сверху -- оставшиеся ряды. То есть получается, что в колоде первые девять карт -- ненужные, потом девять карт -- кандидаты на "то, что надо", и ещё девять ненужных. А потом на три ряда карты раскладываем колонками -- в верхний, в средний, в нижний, и так девять раз. Получается, опять таки, три ряда по девять карт, но в каждом ряду первые три -- заведомо не те, потом три -- кандидаты на то, что надо, и последние три -- опять заведомо не те. Спросив "в каком ряду" и получив ответ, сужаем множество карт до трёх. Снова этот ряд в середину, сверху и снизу "ненужные", и опять раскладываем колонками. Те три, которые "нужные", при этом ложатся в самую среднюю колонку.

В-О-О-Т!> А потом

В-О-О-Т!
> А потом на три ряда карты раскладываем колонками -- в верхний, в средний, в нижний, и так девять раз.
Это очень существенно.
В том варианте, который я знаю, раскладывается любое количество карт в несколько рядов. Весь фокус именно в способе сбора или раскладки карт (в вашем случае - способ раскладки). Т.е. гарантировано две раскладки. А дальше - фантазия фокусника, как более зрелищно достать нужную карту из колоды.
Еще раз прочитал описание фокуса в книге, у вас написано про обе раскладки - три ряда по девять.
Но это так, мелкое замечание. Надеюсь никто из студентов не захочет повторить данный фокус :)

Хотелось бы уточнить вот какой вопрос... Вы приводите примеры, в которых показываете преимущества рекурсии. Но мне попадались статьи, в которых авторы наоборот не советовали использовать рекурсию. Кто прав? Или тут все зависит от конкретной задачи?

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

admin аватар

Про фокус --

Про фокус -- видимо, мне это казалось "очевидным". Но, кстати, "любое" количество карт не подходит, тут именно что точный расчёт. И раскладок на 27 картах нужно три, а не две, мы ведь на каждом шаге получаем один трит информации, а нужно три трита.

Про рекурсию -- естественно, зависит от задачи. А ещё от процессора, на котором это работает.

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

Опечатка или это я не понял

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

Благодарю Вас за прекрасную книгу!

Не совсем понял кое-что в листинге "реализация интерфейсных процедур для Очереди" на стр.372-373.
Почему в одних случаях нужно обращаться queue.first, а в других queue^.first ?

Заранее спасибо

admin аватар

Ой, как досадно

Действительно опечатка, там queue имеет тип "запись", а вовсе не указатель на запись, так что должно быть везде "queue."

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

Но косяк отвратительный. Жалко, что я такое упустил. И спасибо за его выявление.

ошибка

Добрый день.
Нашел ошибку, на с. 174, предпоследнее предложение, где перечень дробей. По-моему, 1/5 в этом списке лишняя, т.к. она делится без периодического остатка.

Спасибо за Ваш труд!

admin аватар

Да нет, тут как раз всё в порядке

Спасибо за вашу внимательность, но 1/5 -- это ведь 0.2. Если применить к 0.2 алгоритм, подробно описанный в книге, последовательность будет такая: 0.2, 0.4, 0.8, 1.6 (отбрасываем единицу, остаётся 0.6), 1.2 (отбрасываем единицу, остаётся 0.2) -- вот мы и зациклились, с периодом в 4 знака. Двоичная дробь будет 0.(0011), эти четыре цифры будут повторяться бесконечно.

Оно и понятно -- не существует такой степени двойки, которая разделилась бы на 5 без остатка.

Если сомневаетесь, можно результат проверить. Обозначим двоичную дробь 0.(0011) за x. Тогда 16x будет 11.(0011) (опять же двоичное), что на 11_2 (то есть на три) больше x. Т.е. имеем равенство 16x=3+x. Отсюда 15x=3, т.е. x = 3/15 = 1/5. Всё, как видим, сходится.

Ошибка

с.188, сноска 58, последняя часть последнего предложения: "..., но никаких других операций над ячейками памяти выполнять ? могли" -- пропущена частица "не".

admin аватар

Факт

Да, точно. Спасибо.

Спасибо! Ещё

Спасибо! Ещё одну замечательную книгу увидет свет.

Если будете исправлять ошибки в будущем издании.

Кажется на стр.77 второй абзац: "команда «ls /etc/*conf.» покажет список файлов с суффиксом .conf" - точка должна стоять после звёздочки, а не в конце?

В туже копилку:

В туже копилку: стр. 391 второй абзац про взаимную рекурсию "/подпрограмма!описание|" - скорее всего ошибка парсинга.

admin аватар

Уже знаю :)

В книге это страница 389, несколько комментов назад это уже обсуждалось. В PDF'е это 391-я страница, потому что в начало добавлены ещё обложка и лицензия. Про этот момент я уже знаю, но всё равно спасибо :-)

admin аватар

Факт

Надо отвыкать использовать точки в команде \verb :-) Это я тупо не заметил, что там точка в середине verb'анутого текста.

Спасибо!

Добрый день,

Добрый день, Андрей.
Начал читать книгу и нашел именно себя. Первый язык PHP, любимая ОС Windows. В оправдание скажу, что уже как год работаю на Ubuntu.

У меня к Вам небольшая просьба.
Я прочитал главу "Теперь немного математики" и понял, что я ничего не понял :). К сожалению, человека, который мне это объяснит нет. Могли бы Вы, посоветовать книгу(и) простую в понимании по этой теме.
Спасибо, Владимир.

Если взять в

Если взять в руки ручку/карандаш и проработать все задачки самостоятельно все станет очень понятно. Я тоже ее "прочитал" и ничего не понял.
Потом взял тетрадь и ручку и понимание пришло. Берете и расписываете все эти флажки, шарики и лампочки. От 1 до сколько необходимо будет для понимания задачи.

Позвольте, я

Позвольте, я отвечу за автора.
По комбинаторике есть простой задачник (с теоретическими вставками и примерами решения) - учебник Тишина В.В. Дискретная математика в примерах и задачах. Также по этому разделу можно почитать Виленкина Н.Я. Комбинаторика, или первые 8-9 параграфов Ежова И.И. Элементы комбинаторики (1977).
По системам счисления - Фомин С.В. Системы счисления (1987).
По алгоритмам и прочим разделам дискретной математики - Кузнецов О.П. Дискретная математика для инженера. Эта книга выдержала множество переизданий (с 1980), и с неё я начинал знакомство с дискретной математикой.
Все указанные книги имеют довольно низкий порог вхождения.

admin аватар

Не правах "автора"

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

admin аватар

Знаете, это

Знаете, это сложно. Я могу назвать много книг, где всё это излагается более системно, фундаментально, последовательно -- и, как следствие, более сложно. А вот таких, где всё то же самое было бы рассказно ещё проще, я не видел. Это не значит, что таких книг нет, просто я их не видел.

опечатка

И ещё в пункте 2.15.5, где стоит длиннющий if написаны || вместо or, авторы Си не даёт-таки покоя.

admin аватар

Тоже есть такое

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

опечатка

На стр. 389 во втором абзаце пункта 2.14.1 в третьей строке в начале какая-то лабуда. Похоже на ошибку при наборе в виме.

admin аватар

Ага

Это там в исходнике вместо \notion стоит \textit. Обидно, я думал, я их все выловил, а вот поди ж ты. Говорили мне, не надо трогать рукопись после корректора :) Вим тут, впрочем, ни при чём совершенно.

Еще одна незначительная придирка

Стр. 66, последнее предложение примечания 19:

> ...а слово «папка», кроме этой сноски, вам больше нигде в тексте не встретится.

Стр. 196, примечание 4:

> Ещё раз напомним о недопустимости использования термина «папка»!

Если воспринимать текст буквально, получается, что автор наврал читателю. Плюс, если уж вообще придираться, слово "папка" есть в другом значении на стр. 446, раздел 2.17:

> ...как проще найти нужную бумагу в шкафу с офисными __папками__, нежели в большом ящике, набитом сваленными в беспорядке бумажками.

Может, изменить конец примечания 19 на что-то вроде "В этой книге мы используем корректную терминологию, а именно, термины "каталог" и "директория", которые считаем равноправными."?

admin аватар

С замечанием согласен, но...

К сожалению, теперь уже это исправить получится только в следующем издании, вероятность которого мне кажется исчезающе малой.

формат А5

Здравствуйте возможно ли сделать книгу в формате А5 для чтения с электронных читалок?

admin аватар

Дык это...

она вообще-то и есть в формате A5, или вы A6 имеете в виду?

О языке

Здравствуйте! Вопрос может не по теме, но хотелось бы узнать ваше мнение. Считаете ли вы JavaScript объектно-ориентированным языком?

admin аватар

Ответ на этот

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

С другой стороны, утверждение о том, что языки без наследования нужно называть не "object-oriented", а "object-based" также нельзя считать общепринятым, хотя оно и популярно.

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

Здравствуйте! Объясните для непосвящённых, пожалуйста, Ваше отношение (или дайте ссылку) к JavaScript в контексте следующего фрагмента: "К тому же они дружно отказываются работать при отключённом в браузере JavaScript. Я попросту не могу никого просить посещать подобные сайты, это исключено"

admin аватар

Это отношение

Это отношение не к самому языку, а к тому, где и как он применяется. Вот тут тред был на эту тему: http://www.stolyarov.info/books/asm_unix#comment-425

Это как с

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

admin аватар

Ничего

Ничего подобного. Кухонный нож бывает полезен. Client side execution не может быть полезен, его использование приводит к массовой компрометации безопасности клиентских машин, то есть это заведомо вредоносная сущность.

Не всегда

В большинстве случаев это действительно так, но ведь не все www-страницы открываются через интеренет, бывают ситуации, когда клиент имеет основания доверять серверу. Например, в компьютерном классе при доступе к локальной странице, либо в случае, когда клиент и сервер физически находятся на одном компьютере. Я имею в виду программы вроде sagemath (http://www.sagemath.org). У этой программы помимо консольного режима работы есть www-интерфейс, который позволяет интерактивно показывать графики. Для этого в браузере должна быть включен javascript, а так же (для показа трёхмерных графиков) ещё и java. Казалось бы, client-side execution, но программа "приехала" не неизвестно-откуда, а с localhost-а. То же самое может иметь место при установке программы в компьютерном классе: очевидно, там клиент доверяет серверу, так как их настраивал один и тот же человек.
Я не утверждаю, что из этого следует, что применение здесь client side execution является правильным --- на мой взгляд, было бы намного лучше, если бы программа имела самостоятельный GUI, не требующий наличия браузера для показа (кстати, именно так сделано в проприетарных альтернативах). Однако компрометации безопасности клиентских машин в данном случае не происходит --- по причинам, изложенным выше.

admin аватар

Ещё как происходит!

Вы из этого браузера можете ходить не только на локальные сайты, но и в Интернет. И, естественно, включив JS для использования этой дебильной софтины с web-интерфейсом, забудете его потом выключить. Ну то есть вы-то не забудете, возможно, но обычный пользователь, не понимающий толком, что такое JS и client side scripting, уж точно не станет заморачиваться постоянным включением-выключением JS. Особенно если учесть, что в "современных" браузерах эту настройку закопали так, что обычный пользователь её просто не найдёт.

Для этого

Для этого существуют различные пользователи в системе и различные профили браузера. Если заморочиться, можно настроить iptables так, чтобы браузер со включённым javascript не имел доступа в интернет.
Упомянутый вами "обычный пользователь" всё это действительно вряд ли настроит, особенно учитывая, что он, скорее всего, сидит под виндой, где всё это, конечно, тоже можно настроить, но 1) это на два порядка сложнее 2) вероятность обхода разграничения полномочий будет выше как минимум из-за большей распростанённости этой системы.
Но в моём комментарии речь шла не о том, что обычный пользователь всё легко настроит, а о том, что компрометации безопасности может не происходить в случае если пользователь клиентской машины понимает, что он делает и зачем. Есть такая фраза: "Так можно делать только тем, кто понимает, что так делать нельзя".

admin аватар

Вы вообще о чём?

Я вам говорю, что существование "интранетных" систем с веб-мордами, завязанными на JS — несомненное зло, поскольку пользователь (обычный, да) в результате с хорошей вероятностью оставит JS включённым; а вы мне в ответ, что профессиональный сисадмин, по-видимому, может проблем избежать.

Ну да, я тоже могу проблем избежать, у меня таки да, под основным аккаунтом браузер с выключенным JS, а для включённого — отдельный аккаунт, где с интервалом раз в месяц всё сносится. Вот только при чём тут я и как это отменяет сказанное мной ранее?

Я думаю, что JS

Я думаю, что JS на сайте может быть полезен. Он ускоряет работу - не нужно постоянно ждать ответа с сервера. С помощью Ajax мы теперь загружаем не всю страницу, а только определенные блоки. И вся мультимедиа, все анимации - это JS. Я думаю, что это не только экономическая выгода(чтобы легче продать), но и творческое выражение людей. И страница "оживает", это тоже приятнее пользователю.

admin аватар

Вы что, не поняли, да?

Ещё раз: JS компрометирует безопасность клиентских машин. Всё, точка, понимаете? Его нельзя применять на сайтах, просто нельзя и всё.

А ваш лепет про то, что что-то куда-то там "оживляется" -- это как раз та причина, по которой я обычно говорю, что только массовые расстрелы спасут цивилизацию. Людей, которые выискивают "достоинства" в JS-нутых страницах, следует лишать права профессиональной деятельности в области IT. Желательно навсегда.

То есть

То есть фронтендщиков "следует лишать права профессиональной деятельности в области IT"? Да на JS столько всего интересного написано! Именно красивого и интересного, это ведь искусство. Вы же не останетесь дома, когда вас пригласят на картинную галерею, только потому, что там с вами на улице может что-то произойти? Или искусство стоит упразднить? Да есть злоумышленники, но это ведь не значит, что все такие. Что все преследуют своими целями взломать вас. Об этом есть поговорка "Волка бояться - в лес не ходить". Возможно, стоит просто усилить защиту клиентских машин. А также научиться отличать мух от котлет.

admin аватар

Руки оторвать

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

Ошибка в предисловии

Не менее часто встречается и другой вариант: учить пытаются, судя по всему, чистому Си (тому, который без плюсов), то есть не рассказывают ни классы, ни контейнеры, ни STL (что, в общем, правильно), ни ссылки, но при этом невесть откуда выскакивают cin/cout, тип bool (которого в чистом Си отродясь не было), строчные комментарии и прочие примочки из Си++.

Вообще-то в Си есть и тип bool, и строчные комментарии.
Не путайте "чистый" Си и "древний" Си.

admin аватар

Это вы не

Это вы не путайте язык Си с мерзким подельем группы международных террористов, которое называется C99 (если говорить о строчных комментариях) и глупейшим набором макросов из stdbool.h (этого НЕТ в языке Си, даже если рассматривать C99)

А что

А что собственно такого плохого в новых стандартах Си? (по поводу новых стандартов плюсов ваше мнение я уже знаю)

admin аватар

По-моему, очевидно

В C99 есть VLA. Дальше можно не смотреть. Ну то есть мне там много чего не нравится, но VLA -- это приговор стандарту сразу и без вариантов.

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

Кстати, есть

Кстати, есть один интересный момент с этим alloca и VLA. https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/Variable-Length.html
> (If you use both variable-length arrays and alloca in the same function, deallocation of a variable-length array also deallocates anything more recently allocated with alloca.)
Т.е. использование VLA вместе с alloca это очень плохая идея

admin аватар

Использование

Использование VLA -- это не просто "плохая идея", это то, чего психически здоровые люди не делают. И это никак не зависит от наличия/отсутствия alloca.

Да, есть VLA, и

Да, есть VLA, и что? Кто-то заставляет его использовать? Еще есть не не определенный стандартом alloca() который работает похожим образом, так что теперь, не использовать компиляторы, которые допускают использование alloca? VLA и alloca всегда можно заменить на malloc и free без потери смысла

admin аватар

Замечу, функция

Замечу, функция alloca существовала раньше C99, и против неё у меня особых возражений нет, поскольку выбор между malloc и alloca -- это обычная оптимизация, и если человеку сказать "будь любезен использовать malloc, а alloca не трогай", он, скорее всего, особо возражать не станет, тем более что на объекты, созданные alloca, накладываются ограничения, очевидные для всех, кто понимает, что такое стековый фрейм, но не очень очевидные для тех, кто это не совсем понимает (а таких, как водится, большинство).

Что касается VLA, то проблема не в том, что кто-то "заставляет" ими пользоваться. Проблема в том, что стандарт "разрешает" ими пользоваться, выдаёт индульгенцию на их использование. А буковок при этом писать нужно несколько меньше, чем для вызова malloc, так что соблазн велик. Когда же руководитель разработки говорит разработчику, что VLA использовать не следует, в большинстве случаев он напарывается на вопрос "но почему, оно же есть в стандарте". Ответ на вопрос "почему", разумеется, существует, но он длинный, пространный и требует понимания таких вещей, о которых большинство кодеров просто не считает возможным задумываться, так что даже если этот ответ оформить в виде текста, массовым ответом на него будет сакраментальное "tl;dr".

> Ответ на

> Ответ на вопрос "почему", разумеется, существует, но он длинный, пространный и требует понимания таких вещей, о которых большинство кодеров просто не считает возможным задумываться, так что даже если этот ответ оформить в виде текста, массовым ответом на него будет сакраментальное "tl;dr".

Что-то я никак не могу понять, почему alloca можно, а VLA нельзя. Проблемы, которые может вызвать использование VLA те же самые, которые может вызвать использование alloca. Я б даже сказал, что использование alloca более опасно: если внутри цикла кто-то сделает alloca то на каждую итерацию цикла будет от стека отбираться кусок, если же использовать VLA то память в стеке будет выделена лишь единожды.
Хотя через alloca так тоже можно сделать:

int a;
void *mem = NULL;
for (a = 0; a < 50; a++)
{
if(mem == NULL)
{
mem = alloca(x);
}
}

Другое значимое отличие alloca от VLA это то, что VLA закрывает выделенную на стеке память после выхода из области видимости, и по-моему это хорошо. Так в чем же проблема? Может есть какая-нибудь готовая статья, объясняющая, что же не так с VLA? Длинных текстов я не боюсь, и сакраментального "tl;dr" у меня не будет

admin аватар

Ну, это уже совсем просто

Тут два момента, один технический, другой скорее психологический.

С технической точки зрения до введения VLA имя локальной переменной при трансляции в объектный код естественным образом превращалось в константное смещение относительно стекового фрейма. После введения VLA имя локальной переменной может превратиться в выражение произвольной сложности, в том числе такое, промежуточные результаты которого не поместятся в регистрах. Как следствие, Си при наличии ЭТОГО перестаёт быть низкоуровневым языком, т.е. заменителем ассемблера; но Си ни в каком другом качестве не нужен, он же крив и кошмарен, если подумать. Высокоуровневые языки есть и получше (и я не уверен, что много найдётся таких, которые хуже).

NB: с alloca, очевидно, никаких подобных проблем не возникает, поскольку она никак не влияет на переменные и вообще не является частью языка. Кстати, вот это вот "не является частью языка" может само по себе рассматриваться как ключевое различие: язык гораздо проще испортить возможностями самого языка, нежели библиотеками. Если бы не понятие "стандартной библиотеки" (которое, замечу, для Си вообще чужеродно), то библиотечные возможности вообще не могли бы никак рассматриваться в роли недостатка языка.

С другой стороны alloca -- это нетривиальная фишка, про которую мало кто знает, и если её кто-то применяет, то этот человек точно знает, что делает. С VLA ситуация прямо противоположна: VLA снимает запрет, соблюдение которого неудобно для обезьянок, но который вообще-то имеет весьма существенные основания. Иначе говоря, применение alloca -- результат обдумывания, применение VLA -- результат нежелания думать.

Но, кстати,

> Другое значимое отличие alloca от VLA это то, что VLA закрывает выделенную на стеке память после выхода из области видимости

alloca ведь делает то же самое: The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed when the function that called alloca() returns to its caller.. Точнее, оно ничего не делает, просто стек восстанавливается в исходном состоянии при возврате из функции, "автомагически" высвобождая всю память, выделенную в текущем фрейме.

А разве

А разве предупреждение компилятора -Wvla не решает обе проблемы (как техническую, так и психологическую)?

admin аватар

Ни черта она не решает

Тогда уж лучше -Werror=vla, надёжнее. Но на самом деле это не решает вообще ничего, остаётся возможность задать вопрос "а зачем мы используем такой флаг", и на этот вопрос приходится отвечать. Ответ, разумеется, есть, дать его несложно, при условии, что этот вопрос вообще будет задан.

Когда я студентам, например, рассказываю, как использовать gcc, про -Wall -g мне есть что сказать, и поскольку речь идёт об экономии испорченной кровушки самих студентов (при неизбежном наступании на грабли вроде 'if(a=b)'), доходит обычно сразу. -Wvla, во-первых, труднее запомнить, и во-вторых, объяснение его нужности далеко не столь понятно, так что большинство просто пропустит мимо ушей, девочки-отличницы запомнят, что "так надо", и всё.

В ситуации коммерческой разработки нужно, чтобы важность этого момента понимал руководитель разработки, а большинство руководителей понимает только одно: быстро, блин! Так что даже если в группе есть разработчик, понимающий, что VLA использовать нельзя, ему в большинстве случаев не удастся убедить остальную группу. Ну и так далее.

Тогда уж лучше

Тогда уж лучше -Werror=vla, надёжнее.

Ну, -Werror по-моему, должен быть включён для всех предупреждений, а не только для -Wvla. Без этого предупреждения компилятора теряют смысл, так как показываются только при полной пересборке проекта. Когда компилятор выдаёт список ошибокна 10 экранов, то, как правило, программист исправляет первую из них и запускает сборку снова, чтобы отсеять те ошибки, которые были следствием уже исправленной. При этом предупреждения в другом файле уже не будут показаны в логе сборки, так как файл "успешно" скомпилировался и второй раз компилироваться не будет. Если указана опция -Werror, то такого, ясное дело, не происходит.

Когда я студентам, например, рассказываю, как использовать gcc, про -Wall -g мне есть что сказать, и поскольку речь идёт об экономии испорченной кровушки самих студентов (при неизбежном наступании на грабли вроде 'if(a=b)'), доходит обычно сразу.

Я бы даже сказал, что и этого маловато. Как минимум, -Wall -Wextra -Wfloat-equal -Werror, а для C++ ещё больше предупреждений вроде -Wnon-virtual-dtor или -Wshadow. Если использовать не gcc, а clang, то там есть флаг -Weverything (в этом случае компилятор начинает ругаться на всё, на что он вообще теоретически умеет ругаться, после этого нужно отключить ненужные предупреждения с помощью -Wno-<название предупреждения>). У gcc такого флага, к сожалению, нет (либо я про него не знаю).

В ситуации коммерческой разработки нужно, чтобы важность этого момента понимал руководитель разработки, а большинство руководителей понимает только одно: быстро, блин! Так что даже если в группе есть разработчик, понимающий, что VLA использовать нельзя, ему в большинстве случаев не удастся убедить остальную группу.

Ну, если руководитель разработки не понимает важность этого момента, то тут уже ничего не поможет. Разве что сработает соображение о том, что программа должна компилироваться и под windows компилятором msvc из Visual Studio. Последний vla вообще не поддерживает, насколько я знаю.
Ну, а если руководитель разработки понимает, что он делает и зачем, то -Wvla будет включён, а неопытный разработчик вряд ли полезет менят опции сборки проекта.

Но в целом, конечно, нельзя не согласиться с тем, что vla придумали несколько странные люди.

admin аватар

Резюме тут, на

Резюме тут, на мой взгляд, очень простое: VLA — возможность дебильная и никогда бы не прожила дольше нескольких лет в нескольких отдельно взятых компиляторах (примерно так живут gnu extensions), если бы не стандарт. Мораль: авторов этого стандарта стоило бы пристрелить. А на самом деле не только этого, нынче все технические стандарты такие.

И флаги компилятора тут абсолютно ни при чём, это просто из другой сказки.

Нет, все как я

Нет, все как я сказал. alloca заканчивает свое действие по завершении функции, VLA же заканчивает свое действие по выходу из скоупа (области видимости), и если будут попытки обращения к этому VLA через указатели, когда как сам VLA был "освобожден", то можно попортить память. Вот пример, который у меня воспроизводится для GCC 4.8.4 под архитектурой x86-64

gcc -std=c99 -O0 test.c

#include <stdio.h>

int test(unsigned char sz)
{
    unsigned char *ptr;
    {
        unsigned char a[sz];
        ptr = a;
    }
    unsigned char b[sz];
    b[1] = 210;
    printf("%u\n", b[1]);
    ptr[1] = 123;
    printf("%u\n", b[1]);
    return 0;
}

int main(void)
{
    test(100);
    return 0;
}

Получаю на выходе

$ ./a.out 
210
123

Из-за каких-то багов или ограничений движка, угловые скобки в include и отступы в коде отсутствуют

admin аватар

А, пардон,

А, пардон, дошло. Я сам редко в чистом Си использую переменные, локализованные в блоке, а не в функции, поэтому не сразу сообразил, о чём идёт речь (самое интересное, что в C++ я, наоборот, постоянно так делаю для объектов, снабжённых деструкторами).

В общем и целом, всё это никак не отменяет сказанного про трансляцию имён локальных переменных и про думающих и недумающих программистов.

P.S. ну угловые скобки оно за html-тэг приняло и отфильтровало :-) Если использовать &lt; и &gt;, всё будет в порядке. А вместо code лучше pre, сейчас добавлю в список разрешённых.

учебник или справочник?

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

admin аватар

Очевидно, что

Очевидно, что это никаким боком не справочник, справочников и без меня хватает, особенно с учётом существования интернета.

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

Так что это скорее некий textbook, книга для чтения, возможно, даже не учебное издание, а скорее популярное.

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

В принципе да, наверное, было бы неплохо придумать какой-то задачник в поддержку книги.

Да!

Неимоверно поддерживаю!

Какой

Какой дистрибутив Linux предпочитает автор для обучения?

admin аватар

Зависит от

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

А дальше, по большому счёту, неважно, какая будет система. Оконник ставится какой-нибудь лайтовый, IceWM, Fluxbox, xfce, мало ли их. Ну а терминал с командной строкой, компиляторы всего, что нужно, всякий make/gdb/valgrind/vim и прочее -- есть везде.

Андрей

Андрей Викторович! Учебник и подобранная обложка классные, спасибо за ваш труд, за доступные знания. Читатели вас ценят и любят!

admin аватар

Почему "подобранная"?

Обложку делал профессиональный дизайнер по моему заказу специально для этой книги, а идею мне подсказала вот эта картинка: https://www.google.ru/search?q=%D1%83%D0%B4%D0%B8%D0%B2%D0%B8%D1%82%D0%B...

Андрей, а

Андрей, а растолкуйте 2 вещи на обложке - перевернутое облако, крылатая рыба.
Со всем остальным, вроде бы, в курсе - костыли подпирающие важные части, переизобрётённые квадратные колёса велосипеда, рассыпанная пачка грабель, о которые набиваешь шишки, жук, он же баг. А вот с теми 2мя - непонятно.
PS: капча безумная.

admin аватар

А чего их растолковывать?

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

А ещё на этой картинке не все видят глобус Индии :-)

Скорее при

Скорее при отладке пришлось локально направить гравитацию вверх, чтобы туча не упала на землю :)

Я же говорил,

Я же говорил, что это Индия, а никакая не Африка! А то Мадагаскар, Мадагаскар…

admin аватар

Ну, ты был

Ну, ты был первым из трёх человек, которые меня таки убедили, что это не Мадагаскар, а Цейлон :-)

Возможная небольшая шероховатость изложения?

стр.54:

> оперативное запоминающее устройство (ОЗУ, англ. RAM от random access memory, то есть память случайного доступа)

стр. 60:

> Оперативная память ^14

> ^14 Можно также встретить термины «основная память» и «оперативное запоминающее устройство» (ОЗУ). В англоязычной литературе используется термин RAM (Random Access Memory), который можно перевести как «память произвольного доступа».

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

admin аватар

Ну да, так оно и есть

Один из, скорее всего, многих косяков, которые не выловили "бета-тестеры".

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".