Претворять планы в жизнь как пишется

Найдено определений: 25 претворить толковый словарьтолковый словарь ушаковапретворить, претворю, претворишь, совер. к претворять, что во что книжн.. 1. превратить что-нибудь
Найдено определений: 25

претворитьпретворить

толковый словарь

толковый словарь ушакова

ПРЕТВОРИ́ТЬ, претворю, претворишь, совер. (к претворять), что во что (книжн.).

1. Превратить что-нибудь во что-нибудь, придать чему-нибудь иной вид, иное содержание (преим. в мифических повестях, поверьях о «чудесах»; устар.). Претворить воду в вино.

2. со словами «в дело», «в жизнь» и т.п. Воплотить во что-нибудь реальное, осуществить какой-нибудь план, какое-нибудь начинание на деле, в действительности. Ленинские предначертания претворены в жизнь. Претворить замысел в дело. Претворить свои планы в жизнь.

толковый словарь ожегова

ПРЕТВОРИ́ТЬ, -рю, -ришь; -рённый (-ён, -ена); совер., что во что (книжн.). Осуществить, воплотить. П. проект в жизнь. П. идею в дело (в реальность, в действительность).

| несовер. претворять, -яю, -яешь.

| сущ. претворение, -я, ср.

энциклопедический словарь

ПРЕТВОРИ́ТЬ -рю́, -ри́шь; претворённый; -рён, -рена́, -рено́; св.

1. кого-что. Устар. Превратить в кого-, что-л., преобразовать. Мороз претворил воду в лёд. Любовь претворила его в мечтателя.

2. что. Воплотить во что-л. реальное, осуществить на деле, в действительности. П. идеи в жизнь. П. планы в действительность.

Претворя́ть, -я́ю, -я́ешь; нсв. Претворя́ться, -я́ется; страд.

академический словарь

-рю́, -ри́шь; прич. страд. прош. претворённый, -рён, -рена́, -рено́; сов., перех.

(несов. претворять).

1. устар.

Превратить во что-л., придать чему-л. иной вид, иное содержание.

Осень жестоко изуродовала сорную глинистую землю, претворив ее в рыжую смолу, цепко хватающую за ноги. М. Горький, В людях.

[Скульптуры Шадра] едины в главном: в романтическом мировосприятии скульптора, в его умении претворить конкретное в социальное. Воронова, Шадр.

2. (обычно в сочетании со словами: „в дело», „в жизнь» и т. п.). Воплотить во что-л. реальное, осуществить на деле, в действительности.

Претворить идеи в жизнь. Претворить планы в действительность.

Волго-Дон — инженерный шедевр, претворивший смелую мысль в жизнь. Федин, Шаг за шагом.

пунктуация и управление в русском языке

что во что. Претворить проект в жизнь. Планы претворить в действительность. Осень жестоко изуродовала сорную глинистую землю, претворив ее в рыжую смолу, цепко хватающую за ноги (Горький).

орфографический словарь

претвори́ть, -рю́, -ри́т (воплотить; претвори́ть в жи́знь)

трудности произношения и ударения

претвори́ть, претворю́, претвори́т (неправильно претво́рит).

формы слов

претвори́ть, претворю́, претвори́м, претвори́шь, претвори́те, претвори́т, претворя́т, претворя́, претвори́л, претвори́ла, претвори́ло, претвори́ли, претвори́, претвори́вший, претвори́вшая, претвори́вшее, претвори́вшие, претвори́вшего, претвори́вшей, претвори́вших, претвори́вшему, претвори́вшим, претвори́вшую, претвори́вшею, претвори́вшими, претвори́вшем, претворённый, претворённая, претворённое, претворённые, претворённого, претворённой, претворённых, претворённому, претворённым, претворённую, претворённою, претворёнными, претворённом, претворён, претворена́, претворено́, претворены́

синонимы

грамматический словарь

полезные сервисы

претворить в жизнь

фразеологический словарь

полезные сервисы

претворить(ся)

словарь ударений

претвори́ть(ся), -рю́, -ри́шь, -ри́т(ся)

морфемно-орфографический словарь

претвор/и́/ть(ся) [воплотить(ся)].

полезные сервисы

претворитьсяпретвориться

толковый словарь

толковый словарь ушакова

ПРЕТВОРИ́ТЬСЯ, претворюсь, претворишься, совер. (к претворяться), во что (книжн.).

1. Превратиться (в поверьях о «чудесах»; устар.). Вода претворилась в вино.

2. со словами «в дело», «в жизнь» и т.п. Воплотиться в чем-нибудь реальном, осуществиться на деле (о каком-нибудь плане, начинании, идее). «…Предсказание Ленина о роли нашей партии уже претворилось в жизнь…» Сталин. Замысел претворился в дело.

толковый словарь ожегова

ПРЕТВОРИ́ТЬСЯ (-рюсь, -ришься, 1-ое лицо и 2-е лицо не употр.), -рится; совер., во что (книжн.). Осуществиться, воплотиться. Идея претворилась в жизнь (в реальность, в действительность).

| несовер. претворяться (-яюсь, -яешься, 1-ое лицо и 2-е лицо не употр.), -яется.

| сущ. претворение, -я, ср.

энциклопедический словарь

ПРЕТВОРИ́ТЬСЯ -ри́тся; св.

1. Устар. Превратиться, преобразоваться во что-л. В руках художника камень претворился в скульптуру.

2. Воплотиться во что-л. реальное, осуществиться. Замысел претворился в жизнь. Теория претворилась в практику.

Претворя́ться, -я́ется; нсв. Претворе́ние (см.).

академический словарь

-ри́тся; сов.

(несов. претворяться). устар.

Превратиться, перевоплотиться во что-л.

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

пунктуация и управление в русском языке

во что. Мысли претворились в дело. Наружность [артиста] сначала как будто невыразительная, ничего не говорящая, но всегда готовая претвориться в самый неожиданный сказочный образ (Куприн).

орфографический словарь

претвори́ться, -ри́тся (воплотиться; претвори́ться в жи́знь)

формы слов

претвори́ться, претворю́сь, претвори́мся, претвори́шься, претвори́тесь, претвори́тся, претворя́тся, претворя́сь, претвори́лся, претвори́лась, претвори́лось, претвори́лись, претвори́сь, претвори́вшийся, претвори́вшаяся, претвори́вшееся, претвори́вшиеся, претвори́вшегося, претвори́вшейся, претвори́вшихся, претвори́вшемуся, претвори́вшимся, претвори́вшуюся, претвори́вшеюся, претвори́вшимися, претвори́вшемся

синонимы

грамматический словарь

полезные сервисы

претвориться в жизнь

синонимы

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

полезные сервисы

Анастасия Бородина: Игорь Евгеньевич, мы тут поспорили с Иваном: что вас всё-таки привело в музыку? Ваня говорит – влюблённость в девушку безответная, я говорю – ваша бабушка, которая была для вас примером. Кто из нас прав? Рассудите.

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

Иван Гостев: Игорь Евгеньевич, как человек с консерваторским образованием подскажите, как вы в сторону эстрадной музыки и в сторону киномузыки впервые перешли? И как у вас вообще сложился этот опыт, и какие есть особенности, если сравнивать классическую, академическую музыку и музыку для кино и эстрады?

Игорь Корнелюк: Я, честно, не думал, что я буду заниматься эстрадной музыкой, и просто первые песни стал писать на спор. У нас в консерватории со мной на одном курсе учился Александр Морозов – замечательный композитор, который много-много лет работает в жанре песни. Мы с ним подружились, очень много общались, музицировали, спорили, и тут он мне как-то во время одной из таких доверительных бесед сказал такую фразу: «Игорь, знаешь, в чём разница между мной и тобой?». Я говорю: «В чём?». Он говорит: «Ты – человек, хорошо обученный, а я – талант». Я говорю: «Саша, а что такое талант?». Он говорит: «Вот ты пишешь сложную, зачастую умозрительную музыку, которая требует подготовленного слушателя, а я пишу простые песни, которые поёт весь советский народ. Ты так не сможешь». И вот мы с ним тогда поспорили на 2 бутылки коньку, что я напишу песню, которую будет петь весь советский народ.

ФРАГМЕНТ ВЫСТУПЛЕНИЯ ИГОРЯ КОРНЕЛЮКА

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

Анастасия Бородина: Но потом же вы увлеклись написанием музыки для кино, потом внезапно уходите писать оперу. И вот хочется спросить: будет какое-то возвращение назад? Может быть, вы снова вернётесь к эстраде или вообще что-то новое ждать от вас в будущем?

Игорь Корнелюк: А я не знаю, я не знаю, как карты лягут. Дело в том, что, видите, песня в последнее время мне стала как бы неинтересна, потому что песни сейчас пишут все, только ленивый не пишет песен, кто может, кто не может. Более того, я знаю, очень много продукции на этом рынке, которую пишут не музыканты вообще. И мне в этом смысле показалось, что как бы участвовать в этом процессе не то чтобы безнравственно, но неинтересно, и поэтому я ушёл в оперу, ушёл в академические жанры. Мы с Региной Лисиц задумывали вот эту штуку и назвали это не оперой, мы назвали это «игра в оперу». Но я бы не очень хотел, чтобы это пелось всё оперными голосами, потому что оперный голос – это вещь хорошая, но она была хороша для музыки XIX века, певец, стоящий на сцене должен петь так, чтобы через оркестр его услышали на галёрке. Сейчас, поскольку техника позволяет петь это чуть ли не субтоном, и, кстати, все кульминации в нашей с Регишей оперой получились тихие и вообще такая тихая музыка, там всё тихое. Я считаю, что самое сокровенное в жизни, когда мы произносим, вот вспомните – все самые важные фразы в жизни, которые вы произносили, вы наверняка их не кричали, вы наверняка их произносили очень интимным, тихим голосом и это правильно. Потом пришлось очень мучиться с оркестровкой, потому что, когда ты делаешь, ты понимаешь, что это не песня, где в 4 минуты выкладываешься, это такой сгусток энергетический, и ты его выдал и всё, а тут ты должен из этого был лепить другие. Вот представляете, когда ты делаешь-делаешь-делаешь сцену большую и вдруг понимаешь, что 2 недели назад, когда ты намекал на главную тему, которая ещё появится, ты на неё слишком откровенно намекнул и получается, что ты 2 недели работал просто впустую. И дальше принимается волевое решение – в мусорное ведро всё это дело и заново. Честно могу вам сказать, что если бы я знал, что это будет так тяжело, может быть, я и с малодушничал и недоделал бы, но поскольку это была мечта всей жизни, я счастлив, что я это осуществил.

Иван Гостев: Игорь Евгеньевич, вот Пётр Ильич Чайковский говорил: «Вдохновение – это гостья, которая не любит посещать ленивых», – вот эти его стандарты: 3 часа в день каждый день сочинять музыку. Как вы относитесь к творческому процессу? У вас это какие-то планомерные занятия, или вы рассчитываете больше, может быть, на вдохновение? Есть ли у вас какие-то ритуалы, которые позволяют его призвать?

Игорь Корнелюк: То, что по юности давалось легко-легко и как бы само, в юности всегда так бывает, ты когда начинаешь заниматься творчеством, такое ощущение, что оно приходит как бы откуда-то сверху, оно само. Люди думают, что так будет происходить всю жизнь. Нет, потому что дальше – будь любезен отработай. И поэтому, чтобы вызвать себе вот это ощущение восторга, когда у тебя дыхание прерывается, и ты весь трепещешь, нужно много-много сидеть за инструментом и искать-искать-искать, поэтому каждый день я рано утром прихожу в студию и играю-играю, работаю по принципу «ни дня без ноты».

Анастасия Бородина: Игорь Евгеньевич, спасибо вам большое, мы рады, что ваша мечта исполнилась! Но мы как фанаты «Города, которого нет», «Билета на балет», в общем, ваших песен ждём от вас новых хитов в будущем.

Игорь Корнелюк: Спасибо! Будем считать так, что ваши слова, да Богу в уши. Пусть оно так и будет.

Анастасия Бородина: Спасибо!

Иван Гостев: Спасибо большое!

Делаем план написания книги. Зачем он А можно без него написать книгу

Как написать книгу, как составить план написания книги? Первый момент — это посмотреть, что творится на рынке книг в данный момент. Потому что он постоянно меняется, что-то выходит новое, какие-то темы всплеск получают, какие-то тренды появляются, кого-то больше печатают. Тоже делают издательства. Они проводят анализ очень серьезный, прежде чем кого-то печатать, продавать. Они никогда не печатают всех подряд, любого, кто написал книгу. Если ты будешь делать бесплатную электронную книгу, надо проанализировать, что творится по этой теме, ответить на вопрос, чем твоя книга отличается от книг конкурентов, что в ней интересного для читателя? Что там реально будет полезного? Если ничего, тогда писать ее пока нет смысла.

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

Третий — это какую проблему решит читатель, прочитав твою книгу. Надо иметь на это четкий ответ, буквально 1-2 фразы. Это короткий план по написанию книги.

Далее четвертый момент — какая тема у книги. Это надо коротко сформулировать, в одно предложение, в одну фразу, о чем она.

Пятый момент, который тоже желательно учитывать. Задуматься над тем, почему люди, прочитавшие эту книгу, должны рекомендовать ее другим.

Последнее, шестое, по плану написанию книги — это зачем ты вообще пишешь книгу, какая у тебя цель. Это тоже важно для себя понимать. Сразу предупреждаю, что книги никогда не пишутся ради денег. Монетизация у тебя должна происходить в другом месте. Ты строишь личный бренд, у тебя есть для этого инструменты, и ты там его монетизируешь. За печатные книги платят очень мало. Должен понимать, зачем ее пишешь, кого ты хочешь в конечном итоге привлечь, как все будешь монетизировать, и для чего тебе эта книга. Буквально на одну страницу надо выписать этот план, дать ответы на вопросы, и тогда понимаешь, для чего вообще эта книга, зачем тратить на нее силы, время, деньги. Потому что деньги нужны на написание книг.

Как написать книгу, а именно с чего начать план написания книги, когда ты планируешь ее создание?

Первое — это что полезное передаешь людям, какую проблему надо решать. Второе — это как будешь ее продвигать и продавать, вплоть до вопроса монетизации, что ты с ней будешь делать. Представь, что ты ее уже написал, а дальше что с ней делаешь? Надо понимать, как будешь делать продвижение книги, есть ли у тебя своя аудитория, может рассылка, лист клиентов в интернет-магазине, свой сайт с хорошей посещаемостью, форум, присутствие в соцсетях, какие-нибудь группы Вконтакте, в Facebook, в Одноклассниках, канал в YouТube раскачанный, большая аудитория в Инстаграме. Электронную книгу можно продавать через свой сайт, некоторые так делают в американском инфобизнесе. Книгу за 10 или 100 долларов через сайт Amazon продают. Самиздат можно сделать, когда ты сам распространяешь печатные копии. Либо ты будешь книгу распространять через издательство. Это надо заранее продумать, потому что тебе нужен договор с издательством, с ним согласовать весь цикл производства.

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

Нельзя брать широкую тему или очень узкую. Например, написать книгу «Как делать дом из красного кирпича». Такая книга никому не будет интересна, потому что слишком узкая тема. Чтобы знать, что сейчас продают, надо проводить небольшое исследование, и от этого отталкиваться. При этом понимать свою возрастную аудиторию, потому что бывают дети, молодежь, взрослые, даже на пенсионеров ориентируются, на мужчин, женщин, на какие-то профессиональные группы узкоспециализированные. Надо понимать, кому предназначается эта книга. Дальше нужна проблема, ее нельзя придумать. Как и в продажах, ты не можешь придумать, что продавать людям. Тебе надо смотреть, что они покупают, чего хотят, ищут в интернете, и это продавать. Тебе надо не придумать, а найти проблему, взять ее небольшую часть, и таким образом делать эту книгу. Соответственно, говоришь на языке аудитории, понимаешь план написания книги, как эти люди разговаривают, что они примут, что нет. Весь контент должен быть уникальным, обращаю на это внимание, то есть он должен быть твоим. Есть случаи, когда нанимают писателей. Эта тяжелая работа, имя человека нигде не светится. Дарья Донцова, например, так пишет. У неё целый пул авторов, десятки, кто за нее пишет. Потом она выводит все под своим брендом, как будто она это написала. Когда продумываешь монетизацию, должен понимать, что аудитория твоя должна быть платежеспособной. Если ты для школьника сделаешь книжку за полторы тысячи рублей, она не продастся, потому что у них нет денег. Если она вне их интересов, тоже не продастся. Надо понимать заранее, у какой аудитории есть деньги. Если будешь выпускать бесплатную книгу для подписки, ты все равно потом захочешь ее монетизировать. В конечном итоге любая книга приводит к монетизации, потому что какой-то процент людей, прочитавших ее, начинают покупать. Должен понимать, что те люди, под которых ты готовишь эту книгу, должны быть платежеспособными. Заранее должна быть продумана монетизация.

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

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

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

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

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

Наибольшая выгода — это создание подписного листа читателей, кто приходит в рассылку, кому ты каждый день можешь отправить письма. Это куда важнее, чем если сразу сделаешь печатную платную книгу. У тебя не будет контактов читателей. Контакт с ними прервался. В современном мире намного выгоднее давать книги за подписку. При этом надо давать качественные книги, не эту ерунду, которую гонят инфобизнесмены. Когда скачиваешь книгу, а там на 20-40 страницах одна реклама. Потратишь 5 секунд на нее и после этого стираешь, она не нужна, от неё никакой пользы. Бессмысленно время тратить на такие книги. Раньше это работало, а сейчас вызывает раздражение. Получается, что у тебя происходит первый контакт с твоим потенциальным клиентом, а ты ему сразу пытаешься дать ерунду. Сначала создай доверие, дай что-то полезное, пусть человек перепроверит, и тогда какой-то процент из них станет твоими клиентами. Прежде, чем писать книгу, надо сначала продумать план, чтобы понять, зачем она выпускается. Обдумать ряд моментов. После этого делать план написания книги и бизнес- план. Это касается продвижения и монетизации. Они идут неразрывно, так как взаимосвязаны. Ни одна книга сама себя никогда не продаст, какая бы хорошая ни была.

Даже именитые российские авторы, которые десятилетия на рынке, занимаются активным продвижением каждой новой книги. Они имеют большие маркетинговые бюджеты на эту задачу, проводят много мероприятий, и только тогда она красиво выстреливает, по-другому не работает в этом бизнесе. Книжный бизнес очень тяжелый.

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

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

Что дальше в плане написания книги?

Дальше идет общая структура книги, независимо от объема. Если ты заметку, статью пишешь, вспомни, как в школе тебя учили писать сочинение. Я их терпеть не мог. Если бы мне кто-то сказал, что буду автором 17 книг, я бы ответил, что не хочу ничего писать. Сочинение на две-три страницы — это уже каторга для меня была, а там книги на сотни страниц. В сочинении есть структура — это вступление, середина, заключение. Во вступлении пишешь, почему с тобой стоит иметь дело, в чем ты специалист, озвучиваешь проблему, которую решаешь, показываешь свои конкурентные преимущества, приводишь какие-то факты или доказательства. Если посмотришь на американский рынок книг, то у них это строго, а у нас на российском рынке только часть освещают, показывают. Когда открываешь переведенную американскую книжку, сначала идет пиар автора, что он супер специалист, какие-нибудь рекомендации от знаменитых людей или компаний, и только потом начинается введение. До написания плана книг, я не понимал, зачем эти 3-5 страниц авторских регалий? То есть в самом начале книги тебе надо продать своему читателю себя и свою книгу, чтобы человек понимал, что эта книга ему нужна для решения его проблемы, специалист, который в этом разбирается. То есть первая страница, блок «введение» — это продажа книги и автора. Середина книги — это рассмотрение проблемы, переходы к ней, разные этапности и ее решение. Приводятся какие-то примеры, результаты. В заключении — это подведение итогов и выводы. В школе нас просили делать выводы. Причем, чтобы они совпадали с выводами учителя. Потому что твой личный вывод никого не интересует, а нужен тот, который хотят услышать. В книге надо тоже подвести итог, дать какое-то решение. Структуру в центральной части можно по-разному делать. Обычно используют две структуры для написания плана книг. Есть структура логической последовательности, когда постепенно из одного вытекает другое и подводит к решению проблемы. У меня есть в нише пикапа 4 книги, в эзотерике 9 книг, одна печатная, 8 — электронных, в бизнесовой теме у меня сейчас 4 электронных книги. Там логическая последовательность, когда идет плавное разворачивание с нуля и дается выход на решение, как это сделать.

Есть другая структура написания плана книги — эта структура типа облака знаний, каталога, когда можно читать книгу с любого места. Ты смотришь по заголовкам, какая проблема тебя интересует, туда переходишь, сразу читаешь, и этого достаточно. Это справочник по большому счету. Любая из этих структур, абсолютно нормальная. Главная задача — это экономия сил и времени читателя. Независимо от структуры, то ли у тебя логическая последовательность, то ли у тебя как каталог, ты все равно экономишь время и силы читателя, чтобы он сам не искал, у него было все в одном месте.

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

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

Язык Си — один из наиболее влиятельных языков программирования за всю историю. Он стал незаменимым инструментом разработки операционных систем, сместив с этого пьедестала языки ассемблера. Изучение Си обязательно для любого уважающего себя программиста. Этот язык любим за свою внешнюю простоту и ненавидим за беспощадность к ошибкам. Благодаря ему у нас есть ядро Linux и тысячи уязвимостей в нём же в придачу. Попробуем понять, что же такое этот противоречивый язык Си — благословение или проклятие?

История языка Си берёт свое начало в недрах американской компании Bell Labs и тесно связана с судьбой операционной системы UNIX. Ее создатели, Кен Томпсон и Деннис Ритчи, разрабатывали свой проект для компьютеров PDP-11, и первые два года их основным инструментом был язык ассемблера. Трудоёмкость написания машинного кода вынуждала искать ему замену, которой в конечном итоге и стал язык Си. С его помощью было полностью переписано ядро операционной системы и большая часть утилит. Язык Си позволял создавать эффективные низкоуровневые программы на PDP-11, практически не используя при этом язык ассемблера.

Со временем встал вопрос портирования UNIX на новые аппаратные платформы. Использование языка Си значительно упростило эту задачу. Ведь если бы в разработке применялся только язык ассемблера, то тогда операционную систему пришлось бы переписывать под каждую компьютерную архитектуру. С другой стороны, исходники UNIX все еще содержали немало кода, созданного специально для компьютера PDP-11. Да и сам язык Си далеко не всегда точно отражал особенности и детали той или иной аппаратной платформы. Последнее еще больше затрудняло процесс переноса и лишало язык одного из его главных достоинств — прозрачной и понятной генерации машинного кода. Чем больше компьютерных архитектур захватывал Си, тем менее очевидной становились его связь с низким уровнем.

В процессе миграции UNIX на новые аппаратные платформы обнаружилась ещё одна проблема. Портированные программы на языке Си исполнялись медленнее, нежели можно было от них ожидать. Чем сильнее отличалась целевая компьютерная архитектура от PDP-11, тем менее эффективным был получаемый код. Чтобы скомпенсировать этот недостаток, разработчики компиляторов всё чаще стали применять неявные оптимизации. И хотя такое решение и улучшало производительность самих программ, Си всё больше отдалялся от низкого уровня. Теперь приходилось не только понимать, как именно определялись конструкции языка для каждой из компьютерных архитектур, но также и то, как они оптимизировались. Разумеется, любой компилятор самостоятельно решал, как именно транслировать исходный код для каждой аппаратной платформы. В итоге написать на языке Си низкоуровневую программу, независящую от используемого компилятора, стало практически невозможно.

Необходимо было понять, как эффективно реализовать высокоуровневые конструкции языка Си, сохранив при этом его низкоуровневые свойства. Попыткой решить эту проблему стала публикация в 1989 году первого стандарта языка. Его принято называть «ANSI C» или «C89», и именно на него мы будем ссылаться в дальнейшем. Создатели стандарта решили окончательно разорвать связь Си с архитектурой PDP-11 и сделать язык полностью высокоуровневым. Была введена так называемая «абстрактная машина» — воображаемый исполнитель кода на языке Си (раздел 2.1.2.3, «Program execution»):

Семантические описания в этом Стандарте описывают поведение абстрактной машины, в которой вопросы оптимизации не имеют значения.

Это означает, что оптимизации компилятора не будут влиять на работу программы, пока её исходный текст согласуется со стандартом. Абстрактная машина должна была решить две проблемы одновременно. Во-первых, следование стандарту давало возможность создавать легко переносимые программы на языке Си. Во-вторых, абстрактная машина могла предоставить компиляторам свободу для оптимизаций. Вот только возникает вполне резонный вопрос — а чем тогда язык Си отличается от любого другого компилируемого языка высокого уровня? Ответ кроется в тексте стандарта. Чтобы всё-таки дать теоретическую возможность программистам писать низкоуровневые процедуры, а значит непереносимые, было введено ещё одно понятие — неопределённое поведение (undefined behavior, раздел 1.6, «DEFINITIONS OF TERMS»):

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

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

Возьмём следующий фрагмент кода на языке Си:

int x = 1;
x = x << sizeof(int) * 8;

Попробуем предположить, какой результат у нас получится. Допустим, мы скомпилировали этот код для процессоров архитектуры ARM. Инструкция битового сдвига в рамках этой аппаратной платформы определена так, что итоговым значением переменной «x» должен быть «0». С другой стороны, мы можем транслировать нашу программу в машинный код архитектуры x86. И уже там битовый сдвиг реализован таким образом, что значение «x» не изменится и останется равным «1». Мы могли бы сделать вывод, что результат работы данного фрагмента кода зависит от того, для какой аппаратной платформы мы его скомпилировали. Но на самом деле это не так.

В действительности данный фрагмент кода может быть обработан компилятором любым возможным и невозможным образом. Причина в следующем: согласно тексту стандарта языка Си битовый сдвиг на величину, большую или равную размеру выражения в битах, является неопределённым поведением. Получается, нет никакой гарантии, что этот кусок кода вообще будет работать. В действительности, даже в рамках одной архитектуры один и тот же компилятор может сгенерировать совершенно разные исполняемые файлы. Приведём примеры компиляции и запуска программы с печатью значения переменной «x». В обоих случаях мы используем компилятор gcc версии 10.2.1 для целевой архитектуры x86-64.

$ cat test.c
#include <stdio.h>

int main()
{
    int x = 1;
    x = x << sizeof(int) * 8;
    printf("%dn", x);
    return 0;
}
$ gcc test.c -o test
$ ./test
1
$ gcc -O test.c -o test
$ ./test
0

Флаг «-O» разрешает компилятору gcc использовать оптимизации исходного кода. То, какие именно механизмы оптимизации могут быть применены, а также какие флаги за них отвечают, зависит от конкретного компилятора. В общем случае невозможно узнать, каким образом будет обработано неопределённое поведение в программе при трансляции исходного кода. Поэтому единственный способ написания переносимых программ на языке Си — это полное избегание неопределённого поведения при разработке.

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

* (char *) 0;

Разумеется, никто в здравом уме не станет писать что-то подобное в своей программе. Однако совсем необязательно делать разыменование нулевого указателя явным образом, чтобы вызвать неопределённое поведение. В цикле статей «What Every C Programmer Should Know About Undefined Behavior» на сайте blog.llvm.org приводится фрагмент кода, подтверждающий это:

void contains_null_check(int *p)
{
    int dead = *p;
    if(p == 0)
        return;
    *p = 4;
}

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

void contains_null_check(int *p)
{
    if(p == 0)
        return;
    *p = 4;
}

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

void contains_null_check(int *p)
{
    int dead = *p;
    if(0)
        return;
    *p = 4;
}

Так как мы разыменовываем указатель до его проверки, то компилятор спокойно решает, что сам указатель никогда не будет нулевым. Благодаря этому сравнение «p == 0» заменяется на выражение, всегда возвращающее ложь. Затем компилятор запускает первый механизм оптимизации и убирает «мертвый» код:

void contains_null_check(int *p)
{
    *p = 4;
}

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

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

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

void *memset(void *ptr, int value, size_t num);

memset записывает «num» байтов со значением «value» по адресу «ptr». Несмотря на то, что параметр «value» имеет тип int, в действительности используется лишь его младший байт. Функция активно применяется для обнуления больших массивов данных, однако компилятор и сам частенько любит вставить её вызов туда, где это нужно и не очень. Так, любопытный случай обсуждался 15 апреля 2018 года на форуме osdev.org. Пользователь под ником ScropTheOSAdventurer создал тему, в которой рассказал о процессе разработки собственной учебной операционной системы. На свою беду он разрешил компилятору оптимизировать исходный код проекта, в результате чего последний перестал работать. В процессе отладки программист обнаружил ошибку в следующем фрагменте кода:

void *memset(void *ptr, int value, size_t num)
{
    unsigned char *ptr_byte = (unsigned char *) ptr;
    for(size_t i = 0; i < num; ptr_byte[i] = (unsigned char) value, i++);
    return ptr;
}

Для своей операционной системы разработчик решил использовать собственную реализацию функции memset. Но он не учёл, что в процессе трансляции компилятор gcc обнаружит в этом коде весьма заманчивую возможность для оптимизации. Фактически функция была в итоге преобразована к следующему виду:

void *memset(void *ptr, int value, size_t num)
{
    return memset(ptr, value, num);
}

Вполне вероятно, что среди разработчиков компилятора gcc были непревзойденные мастера софистики. В любом случае способности компилятора к оптимизациям явно превосходят все доступные человеческому разуму пределы.

Приведем еще один пример с функцией memset. Компилятор способен не только создавать её вызовы на пустом месте, но и выкидывать их из исходного кода по собственному желанию. Так, в криптографических программах зачастую бывает полезно стирать все данные из памяти после того, как они перестают быть нужными. Обычно такое поведение является избыточным, однако представим себе следующую ситуацию. Ваша программа работает с базой данных пользователей, хранящей их имена и пароли, и вы описали примерно такую функцию:

int check_password(const char *pwd)
{
    char real_pwd[32];
    get_password(real_pwd);
    return !strcmp(pwd, real_pwd);
}

Есть лишь одна проблема — после вызова check_password в стеке останется строка с настоящим паролем пользователя. Если в вашей программе есть хотя бы одна уязвимость, позволяющая читать данные из памяти, то существует реальная вероятность украсть пароль из стека. Примером подобной уязвимости стал печально известный баг «Heartbleed». Чтобы снизить возможные риски, проще всего очистить содержащий пароль фрагмент стека:

int check_password(const char *pwd)
{
    int result;
    char real_pwd[32];
    get_password(real_pwd);
    result = !strcmp(pwd, real_pwd);
    memset(real_pwd, 0, sizeof(real_pwd));
    return result;
}

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

Одной из наиболее коварных разновидностей неопределённого поведения является strict aliasing. Термин может быть переведён как «строгое наложение», однако традиционного названия на русском языке у него не существует. По этой причине мы будем использовать оригинальный английский термин. Текст стандарта дает такое описание для strict aliasing (раздел 3.3, «EXPRESSIONS»):

Значение объекта должно быть доступно только с помощью lvalue-выражения одного из следующих типов:

— объявленный тип объекта,

— квалифицированная версия объявленного типа объекта,

— знаковый или беззнаковый тип, соответствующий объявленному типу объекта,

— знаковый или беззнаковый тип, соответствующий квалифицированной версии объявленного типа объекта,

— тип массива, структуры или объединения, который включает в себя один из вышеупомянутых типов среди своих членов (включая, рекурсивно, член внутренней структуры, массива или объединения),

— символьный тип.

Проще всего strict aliasing проиллюстрировать на конкретном примере:

int x = 42;
float *p = &x;
*p = 13;

Чтобы вызвать неопределенное поведение, достаточно обратиться к какой-либо переменной по типу, несовместимому с объявленным. Это ограничение можно обойти, применив символьный тип (char), на который не распространяются правила strict aliasing:

int x = 42;
char *p = &x;
*p = 13;

Вот только расчленение переменной на символы может оказаться трудоемкой задачей. Придется учитывать размер данных, а также используемый порядок байтов. Избежать неопределённого поведения можно также с помощью объединений (union):

union u { int a; short b };
union u x;
x.a = 42;
x.b = 13;

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

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

int get_pixel(const char *buf, int width, int x, int y)
{
    buf += get_header_size(buf);
    return ((const int *) buf)[y * width + x];
}

При вызове функции ей передается адрес области данных с содержимым файла, включая его заголовок, ширину изображения, а также координаты пикселя, цвет которого следует вернуть. Вместо типа int мы могли бы выбрать любой другой с известным нам размером. Но все это неважно, потому что функция get_pixel абсолютно неверна с точки зрения стандарта, так как нарушает правила strict aliasing. Чтобы использовать каламбур типизации, придется переписать весь код, связанный с используемым буфером, в том числе и тот, который ответственен за чтение файла.

Существует огромное количество примеров программ, не удовлетворяющих правилам strict aliasing. В их число входит знаменитая функция вычисления быстрого обратного квадратного корня из игры Quake 3:

float FastInvSqrt(float x)
{
    float xhalf = 0.5f * x;
    int i = *(int *) &x;
    i = 0x5f3759df - (i >> 1); /* What the fuck? */ 
    x = *(float *) &i;
    x = x * (1.5f - (xhalf * x * x));
    return x;
}

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

Остается один вопрос — зачем вообще нужен этот strict aliasing? Все дело в том, что он позволяет создателям компиляторов применять крайне агрессивные оптимизации исходного кода. Правила strict aliasing распространяются на обращения к любой памяти, в том числе и динамической. Так комитет стандартизации отметил, что следующий фрагмент кода (источник):

void f(int *x, double *y)
{
    *x = 0;
    *y = 3.14;
    *x = *x + 2;
}

может быть преобразован таким образом:

void f(int *x, double *y)
{
    *x = 0;
    *y = 3.14;
    *x = 2;
}

Согласно правилам strict aliasing указатель y не может содержать адрес того же участка памяти, что и указатель x. Именно этот факт и позволяет заменить выражение «*x = *x + 2» на «*x = 2». Активное использование компиляторами подобных оптимизаций сломало огромное количество старого кода. Так, в письме от 12 июля 1998 года один из разработчиков компилятора gcc Jeff Law, отвечая на вопросы по strict aliasing и связанными с ним ошибками, пишет (источник):

> Существует очень много кода, который нарушает правила strict aliasing. Одним из таких примеров является «переносимая» универсальная функция контрольной суммы IP, которая содержится в исходных кодах BSD для работы с сетями.

ИМХО, такого кода становится все меньше и меньше — современные компиляторы уже какое-то время используют strict aliasing в анализе, в результате чего люди были вынуждены исправлять свой код. Безусловно, это не относится к Linux и некоторым другим свободным проектам, так как они используют только gcc.

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

Укажите им на стандарт языка Си :-) :-)

Правила strict aliasing для компилятора gcc можно разрешить, используя флаг «-fstrict-aliasing», и запретить флагом «-fno-strict-aliasing». Последний рекомендуется применять, если вы не уверены, нарушаете ли вы текст стандарта — скорее всего, нарушаете. Говоря об упомянутом в письме ядре Linux, его автор Линус Торвальдс также дал свою оценку strict aliasing в частности и работе комитета в целом. Так, критикуя желание одного из разработчиков операционной системы лишний раз перестраховаться от нарушения стандарта, Линус написал такое письмо (источник):

Честно говоря, все это кажется мне сомнительным.

И я не о самих изменениях — с этим я могу смириться. Но вот обоснование этих самых изменений — абсолютная и полная чушь, причем весьма опасная.

Дело в том, что использование объединений для реализации каламбура типизации — это обычный и СТАНДАРТНЫЙ для этого способ. В действительности он является документированным для gcc, и используется в том случае, если вы, будучи не слишком умным (оригинал: «f*cking moron»), применили «-fstrict aliasing», и теперь вам необходимо избавиться от всего того ущерба, который навязывает этот мусорный стандарт.

Энди, что послужило причиной для всего этого идиотизма? И не надо говорить мне, что текст стандарта «недостаточно ясный». Текст стандарта, совершенно ясно, является дерьмовой чушью (см. выше о правилах strict aliasing), и в таких случаях его нужно игнорировать. Для этого необходимо использовать средства компилятора, чтобы избежать ущерба. Аналогично нужно поступать и в ситуациях, где нет полной ясности.

Это то, почему мы используем «-fwrapv», «-fno-strict-aliasing» и другие флаги.

Я уже говорил об этом раньше и повторю еще раз: когда текст стандарта противоречит реальности — он является обычным куском туалетной бумаги. Он не имеет абсолютно никакой важности. В действительности, вместо него я лучше возьму рулон настоящей туалетной бумаги — так хотя бы я не испачкаю свою задницу чернилами (оригинал: «won’t have splinters and ink up my arse»).

Видимо, Линус Торвальдс плохо изучил язык Си — настоящему программисту на Си такое в голову бы не пришло.

Впрочем, одним лишь strict aliasing стандарт не полон. Чтобы вызвать неопределённое поведение, необязательно даже разыменовывать указатель:

void f(int *p, int *q)
{
    free(p);
    if(p == q) /* Undefined behaviour! */
        do_something();
}

Использование значения указателя после того, как память по нему была освобождена, запрещено текстом стандарта (раздел 4.10.3, «Memory managment functions»):

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

Программисту важно понимать, что указатели в Си не являются низкоуровневыми. Стандарт постарался полностью искоренить какую-либо связь языка с реальным миром. Даже сравнение указателей, ссылающихся на разные объекты, объявлено неопределённым поведением (раздел 3.3.8, «Relational operators»):

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

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

int *p = malloc(64 * sizeof(int));
int *q = malloc(64 * sizeof(int));
if(p < q) /* Undefined behaviour! */
    do_something();

Однако наиболее интересным примером здесь будет служить исходный код следующей программы:

#include <stdio.h>

int main()
{
    int x;
    int y;
    int *p = &x + 1;
    int *q = &y;
    printf("%p %p %dn", (void *) p, (void *) q, p == q);
    return 0;
}

Если транслировать приведенный выше текст компилятором gcc, передав ему флаг «-O», то полученный исполняемый файл при запуске выдаст примерно следующую строку:

0x1badc0de 0x1badc0de 0

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

Большая часть примеров, связанных с работой указателей, была взята с сайта kristerw.blogspot.com. На нём вы сможете найти больше информации о текстах стандарта языка Си, а также загадочных оптимизациях компиляторов.

Может показаться, что в случае выключенных оптимизаций все вышеописанные проблемы обойдут вас стороной. Просто не передавайте компилятору флаг «-O», и вы получите тот результат, на который рассчитываете. Но на самом деле это не так. В январе 2007-ого года на сайте gcc.gnu.org пользователь под ником felix-gcc выложил исходный код следующей программы:

#include <assert.h>

int foo(int a) {
  assert(a + 100 > a);
  printf("%d %dn",a + 100, a);
  return a;
}

int main() {
  foo(100);
  foo(0x7fffffff);
}

Функция foo проверяет на переполнение сумму поданного знакового числа и константы «100». Как известно, на подавляющем большинстве компьютерных архитектур отрицательные числа задаются в виде дополнительного кода. В случае переполнения такое число меняет знак на противоположный, благодаря чему проверка «a + 100 > a» возвращает ложь. В теле функции main felix-gcc дважды вызывает foo. Сначала он подает на вход число, которое не приведёт к переполнению. Затем, исходя из того, что размер типа данных int равен четырем байтам, felix-gcc вызывает foo с наибольшим положительным числом данного типа. Логично предположить, что в таком случае сравнение вернёт ложь, и assert прервёт работу программы. Однако вот какой вывод получил felix-gcc после запуска исполняемого файла:

200 100
-2147483549 2147483647

Фактически gcc решил удалить проверку на переполнение, и это при том, что никаких флагов компилятору передано не было. И что еще интереснее, ранние версии gcc при тех же условиях не убирали проверку, в результате чего получаемая программа вела себя иначе. На резонную просьбу felix-gcc исправить неожиданный баг компилятора ответил пользователь под ником Andrew Pinski. Будучи разработчиком gcc, Andrew Pinski заметил, что данное поведение не является ошибочным. Более того, он сам оказался автором изменения в коде компилятора, которое и создало столь странный результат. Далее приводится фрагмент диалога felix-gcc и Andrew Pinski. Комментарии излишни:

Andrew Pinski
Переполнение знакового числа — это неопределённое поведение в тексте стандарта языка Си, используйте беззнаковый тип или флаг «-fwrapv».

felix-gcc
Вы должно быть шутите?
Различные проблемы безопасности вызваны переполнениями чисел, и вы просто так говорите мне, что в gcc 4.1 я больше не могу тестировать их для знаковых типов? Вы явно чего-то не понимаете. ДОЛЖЕН быть способ обойти эту проблему. Существующее программное обеспечение использует знаковые числа, и я не могу просто поменять тип на беззнаковый — мне все равно нужно проверить переполнение! Не похоже, что я мог бы использовать какой-нибудь обходной путь для этого. Что вы хотите от меня — чтобы я привел тип к беззнаковому, сдвинул вправо на один, затем сложил или что вообще?!
ПОЖАЛУЙСТА, ОТМЕНИТЕ ЭТО ИЗМЕНЕНИЕ. Оно создаст СЕРЬЁЗНЫЕ ПРОБЛЕМЫ БЕЗОПАСНОСТИ во ВСЕВОЗМОЖНЫХ ПРОГРАММАХ. Меня не волнует, что ваши стандартизаторы говорят о том, что gcc исправен. ВСЕ ЭТО ПРИВЕДЁТ К ТОМУ, ЧТО ЛЮДЕЙ ВЗЛОМАЮТ. Я обнаружил эту проблему, так как одна из проверок безопасности, которая предотвращает взлом, провалилась.
ЭТО НЕ ШУТКА. ИСПРАВЬТЕ ЭТО! СЕЙЧАС ЖЕ!

Andrew Pinski
Я не шучу, стандарт языка Си прямо говорит, что переполнение знакового числа — это неопределённое поведение.

felix-gcc
Так, послушайте, Эндрю, вы что, действительно думаете, что эта проблема исчезнет, если вы продолжите закрывать баги достаточно быстро? Проверка, которую я написал, покрывала все возможные ситуации. Не требуется даже уточнения того, что за тип используется — указатель, беззнаковое или знаковое число. Ну, указатели вы тоже сломали, но ваши изменения были исправлены. Парень, который сделал это тогда, должен появиться здесь, нам нужен кто-то с трезвой головой и видением ситуации как у него.
Давайте посмотрим правде в глаза — вы облажались по полной (оригинал: «fucked up this royally»), и теперь вы пытаетесь прикрыть все ошибки как можно скорее, чтобы никто не заметил, сколько ущерба вы нанесли. Вы, сэр, непрофессиональны и позорите команду разработчиков gcc. Эта ошибка останется открытой до тех пор, пока вы не вернёте все обратно или не сделаете упомянутый вами флаг по умолчанию. Пока вы будете ломать программы, чьи авторы по глупости включили оптимизации, мне всё равно. Но я не позволю вам делать моё окружение менее безопасным только потому, что ваш непрофессионализм не позволяет вам разобраться с оптимизациями после того, как было показано, что они наносят больше вреда, чем пользы. Сколько еще доказательств вам необходимо предоставить? Боже мой, да autoconf считает, что ваши «оптимизации» нужно отключать повсеместно. Вы вообще замечаете взрывы вокруг самих себя?

Andrew Pinski

http://c-faq.com/misc/sd26.html

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

felix-gcc
МОЙ КОД НЕ СЛОМАН.
Попытки обесценить проблему или оскорбить меня ничего не решат.

Andrew Pinski
Вы написали ошибку, поэтому я и решил, что ваш код сломан.

felix-gcc
Итак, скажите мне, какая часть моей аргументации вам непонятна? Я мог бы использовать слова попроще, чтобы вы смогли меня понять на этот раз.
Ребята, ваша задача — это не просто реализовать стандарт Си. Вы также обязаны не нарушать работу программ, которые зависят от вас. А от вас зависит МНОГО программ. Когда вы нарушили точность вычислений с плавающей точкой, то вы сделали это доступным с помощью флага (-ffast-math). Когда вы добавили strict aliasing, вы так же сделали эту функцию доступной через флаг (-fstrict-aliasing). Если я правильно помню, вы тогда тоже цитировали текст стандарта, пока люди с более адекватным пониманием мира вас не остановили. И я собираюсь оставить эту ошибку открытой до тех пор, пока не повторится та же история.

Andrew Pinski
Я думаю, нам не следовало делать это необязательным, но меня не было в тот момент, когда было принято это решение. Также помните, что у нас был релиз, когда strict aliasing был включен, но затем нам пришлось его отключить по умолчанию. За это время люди исправляли свои программы, пока оптимизация была активна. И мы уже сделали оптимизацию знакового переполнения опциональной с помощью «-fwrapv». Я не понимаю, к чему вы приводите свои аргументы.

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

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

felix-gcc
Знаете ли вы, что ракета Ариан-5 взорвалась (и могла убить людей!) из-за ошибки переполнения? Что если люди погибнут из-за того, что вы решили, что стандарт позволяет вам выкидывать проверки безопасности, написанные людьми?

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

felix-gcc
Еще раз: НЕ ИМЕЕТ ЗНАЧЕНИЯ ТО, ЧТО ГОВОРИТ СТАНДАРТ. Вы сломали программы, и люди пострадали от этого. Теперь верните все обратно. Меньшее, что вы можете, это сделать «-fwrapv» по умолчанию. Вам все еще придётся заставить его работать правильно (я слышал, что он неверно работает в определенных ситуациях), но это уже другая история.

Andrew Pinski
Он будет по умолчанию в тех языках, где определено именно такое поведение. Я дал вам способ написания проверок переполнения, и если вам не нравится то, что говорит стандарт языка Си, то это не моя вина.
Запомните: компилятор gcc также является оптимизирующим компилятором, и если вам нужны оптимизации, то вы должны следовать правилам того языка, на котором вы пишете, вместо создания неверных программ, что и происходит с Си и Си++ в целом.

felix-gcc
В ранних версиях компилятора такое поведение происходило только в случае включённых оптимизаций. Если немножко присмотреться, то окажется, что все ваши аргументы ничего не стоят.
Потому как gcc 4.1 выкидывает этот код уже без включённых оптимизаций. Вот и все ваши аргументы.
Пожалуйста, сделайте «-fwrapv» по умолчанию, и я заткнусь.

Andrew Pinski
Попробуйте проверить время исполнения программы с «-fwrapv» и без него. Вы увидите, что без него код работает быстрее.

Пытаясь уйти в обсуждение оптимизаций компилятора, Andrew Pinski решил тем самым оправдать свою позицию. В процессе он, однако, упомянул куда более «интересную» аргументацию:

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

А в самом конце обсуждения Andew Pinski заявил следующее:

Я бы принял вашу идею о включении «-fwrapv» по умолчанию, если бы не существовало способа для проверки переполнения до того, как оно случилось, но он есть. Да, мы сломаем код, который был написан, исходя из предположения о том, что знаковое переполнение возможно. Но я думаю, что это та цена, которую мы можем принять.

В заключение хочется привести еще одну цитату Линуса Торвальдса:

Разработчики gcc больше заинтересованы в попытках выяснить, что еще им позволяет делать стандарт, чем в том, как заставить вещи действительно работать.

И в этом, похоже, заключена главная проблема языка Си. Но подобное не могло произойти на пустом месте — в конечном итоге мы сами позволили этому случиться. Язык Си уже очень давно перестал выполнять возложенные на него функции и превратился в уродливую пародию на самого себя. Но мы этого не заметили, потому что смирились с тем, что наши программы не работают. Мы, как программисты, настолько привыкли к ошибкам, что они стали неотъемлемой частью нашей жизни. Зачастую на отладку и тестирование программ уходит больше времени, чем на проектирование и написание самого кода. И ведь это немудрено — людям свойственно ошибаться. Большую часть багов и уязвимостей программисты вносят случайно, совершенно не задумываясь, и мы ничего не можем с этим сделать. Однако неизбежность ошибок не оправдывает их существование. Задача программиста в том, чтобы писать код, который работает. Даже если это неочевидно, трудно и невозможно, мы не имеем права делать ошибки. Потому что иначе все бессмысленно, и мы перестаем понимать, что можно делать, а что нельзя, что красиво, а что уродливо. В погоне за эффективностью разработчики компиляторов забыли о том, для чего на самом деле нужен язык Си. Он инструмент программиста, а плохим инструментом нельзя написать хорошую программу. Эта история — показательный пример того, что не всякая деятельность плодотворна, и не каждое изменение ведет к лучшему результату. Стараниями комитета стандартизации и разработчиков компиляторов мы в конечном итоге потеряли язык Си. Как инструмент разработки он стал абсолютно бесполезен и даже вреден, и мы обязаны признать это. В противном случае наши программы никогда не будут работать. Пренебрежительное отношение к ошибкам должно уйти в прошлое, а вместе с ним должен умереть и язык Си.

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

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

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

Соавтор статьи: @aversey

Изначальная публикация: cmustdie.com

Геймдев манит международным масштабом и высокими зарплатами. В чем привлекательность игровой индустрии и как в нее попасть? Разбираемся вместе с директором образовательных проектов VK Анной Степановой

По данным аналитической компании Newzoo, объем мирового игрового рынка по итогам 2021 года составит $175,8 млрд. Российский игровой рынок тоже обширный. За последние четыре года отечественная индустрия игр выросла в 1,6 раза. Как прогнозирует MY.GAMES, объем российского рынка видеоигр в 2021 году может составить ₽165,6 млрд. Аналитики оценивают его рост в 1%, в то время как в 2020 году на фоне длительного локдауна рынок вырос на 35% и стал одним из немногих, не пострадавших от пандемии, а наоборот — преуспевших.

Ожидается, что рынок ПК-игр по-прежнему останется самым крупным сегментом в стране. Несмотря на то, что за год он сократится на 4,6%, его объем в 2021 может составить ₽78,1 млрд. На втором месте будет сегмент мобильных игр. В 2021 году он может вырасти на 10% и составить ₽73,8 млрд, по-прежнему оставаясь основным драйвером роста для всего рынка видеоигр в России. На последнем месте идет сегмент консольных игр, объем которого в текущем году может снизиться на 5% до ₽13,64 млрд.

У индустрии игр становится все больше поклонников по всему миру. Многие из них задумываются о карьере в геймдеве, но не знают, с чего начать. Как показали результаты опроса российских геймеров в возрасте от 10 до 45 лет, 40% считают карьеру в индустрии игр перспективной, при этом 45% не знают, как получить необходимое образование, чтобы в нее попасть. А между тем возможностей сегодня более чем достаточно.

«Попасть в игры» хотят не только взрослые, но и дети. Согласно результатам опроса VK Образования среди российских школьников, треть учеников средней школы хотели бы в будущем работать в сфере разработки игр. 38% считают геймдев перспективным направлением для построения карьеры. Большинство школьников (76%) хотели бы, чтобы в их школах появились уроки или дополнительные занятия по разработке игр.

Фото:«Бомбора»

Сила притяжения

Игровое направление с каждым годом становится все более востребованной сферой для построения карьеры — по данным MY.GAMES, если всего несколько лет назад во всем мире в год по направлению работы в игровой индустрии было порядка 3 тыс. вакансий, то сегодня только в нашей стране игровые компании ежегодно ищут более 40 тыс. специалистов

С развитием геймдева появляется все больше работодателей, которые ищут гейм-дизайнеров, графических дизайнеров, комьюнити-менеджеров, разработчиков игр и других ИТ-специалистов. Результаты исследования Scream School и HH.ru показывают, что количество таких компаний в 2020 году превысило 1600.

По оценкам рекрутинговой компании, специализирующейся на подборе сотрудников для игровых студий, VALUES VALUE и портала для поиска работы в геймдеве InGame Job, в российской индустрии игр в 2021 году медианная зарплата выросла на 12%.

Фото:Unsplash

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

  • Интересные и амбициозные задачи: геймдев — индустрия на стыке творчества и современных технологий, это значит, что скучно здесь не бывает; кроме того, она постоянно растет — недостатка в интересных проектах не предвидится.
  • Отсутствие границ: можно жить, например, в Воронеже, сотрудничать с игровой студией из Москвы или даже из какого-нибудь города в США и получать соответствующую зарплату.
  • Большое количество специализаций: построить успешную карьеру в геймдеве могут не только разработчики, но и иллюстраторы, аниматоры, маркетологи и представители других творческих и гуманитарных профессий.

Свое место в геймдеве

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

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

Фото:Unsplash


Фото: Unsplash

Кто делает игры

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

Разработчик

Чем занимается: пишет код на игровом движке (самые популярные — Unity и Unreal Engine).

Что нужно: языки программирования (в зависимости от платформы — мобильной, ПК- или консольной), теория программирования, навыки работы с игровыми движками.

Тестировщик

Чем занимается: тестирует игры и находит ошибки.

Что нужно: навыки программирования, внимательность, усидчивость.

Гейм-дизайнер

Чем занимается: разрабатывает правила и содержание игрового процесса.

Что нужно: базовые знания в областях разработки игр, математики и физики, навыки программирования, рисования и 3D-моделирования, художественный вкус, сильные коммуникативные навыки.

Игровой художник

Чем занимается: отрисовывает 2D- и 3D-графику.

Что нужно: знание академических основ рисунка, живописи и композиции, умение работать со светом и тенью и грамотно выбирать цвета, инженерная база (для 3D-художника), навыки работы в Adobe Photoshop, Illustrator или CorelDRAW, базовые знания английского языка.

Аниматор

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

Что нужно: знание основ 3D-графики, навыки работы в Autodesk Maya, понимание бодимеханики, сильные коммуникативные навыки.

Саунд-дизайнер

Чем занимается: отвечает за звуковое оформление игры (иногда для его создания привлекаются целые оркестры или оперные певцы).

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

Игровой продюсер

Чем занимается: следит за бюджетом игры, соблюдением дедлайнов — контролирует весь проект в целом.

Что нужно: сильные менеджерские качества, понимание трендов индустрии и интересов аудитории.


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

Игровой сценарист

Чем занимается: разрабатывает сюжет, вселенную, героев и решает, какую историю рассказать игроку.

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

Копирайтер

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

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


Однако игру мало создать. Чтобы она заняла свое место на рынке и завоевала любовь геймеров, нужно заниматься продвижением и поддержкой интереса к ней. Это зона ответственности таких специалистов, как маркетолог и комьюнити-менеджер.

Маркетолог

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

Что нужно: навыки работы в digital (инфлюенс-маркетинг, таргетинг, трафик-менеджмент, понимание трендов игровой индустрии и ее продвижения, сильные коммуникативные навыки.

Комьюнити-менеджер

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

Что нужно: понимание специфики игровой аудитории, кризис-менеджмент, умение анализировать проблемы игроков и решать их, навыки копирайтинга.

Почему надо начинать со школы

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

Абсолютному большинству специалистов в геймдеве потребуется знание английского языка. Кстати, медианная зарплата растет пропорционально его уровню: от $1000, если человек понимает лишь некоторые слова и фразы (элементарный уровень), до $2000, если он способен бегло говорить на английском и хорошо понимает его на слух (продвинутый уровень и выше).

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

Чтобы флора и фауна игровой вселенной, а также персонажи выглядели реалистично (даже если они сплошь сказочные), пригодятся знания биологии. Чтобы соответствовали действительности траектории полета снарядов и разлета осколков при взрывах, а движения персонажей и объектов в космосе не противоречили закону всемирного тяготения, не обойтись без знаний физики и геометрии.

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

Фото:Universal University

Пусть меня научат

Согласно результатам исследования MY.GAMES, практически каждый второй российский геймер (49%) считает самым важным критерием для начала карьеры в индустрии игр наличие хорошего образования. При этом 45% не знают, где такое образование можно получить.

Чтобы помочь поклонникам видеоигр превратить увлечение в профессию, эксперты MY.GAMES совместно с Дальневосточным федеральным университетом составили список программ по направлению геймдева в России. Желающим любого возраста есть из чего выбрать — в первоначальную редакцию (список пополняется) вошли 136 образовательных проектов: 32 программы высшего образования (12 — магистратуры, 20 — бакалавриата), семь — среднего образования, 23 программы повышения квалификации и профессиональной переподготовки, 55 профессиональных курсов и 19 курсов для детей.

Компании, заинтересованные в найме квалифицированных специалистов, активно работают с вузами. Например, VK (на тот момент — Mail.ru Group) еще несколько лет назад начала совместно с вузами готовить специалистов в игровой индустрии: в 2018 году в Воронежском государственном университете появился проект по тестированию игр, а позже в БФУ имени И. Канта открылся курс «Разработка игр на Unity». Сегодня можно учиться и дистанционно — для студентов и аспирантов любых российских вузов работает дистанционная образовательная программа по разработке игр на Unity и серверных приложений на Java.

Компании проводят и масштабную профориентацию для школьников. В этом году их знакомили с разработкой игр. В «День ИТ-знаний» эксперты из игровой индустрии рассказали ребятам о полном цикле производства игр — от появления идеи до запуска и развития проекта — и о том, как построить карьеру в этой сфере. Этой же теме был посвящен этап всероссийского проекта «Урок цифры», организованный компанией VK. Школьники смогли примерить на себя профессии из игровой индустрии, приняв участие в разработке игры в формате интерактивного тренажера.

В качестве самого важного критерия выбора образовательной программы желающие развиваться в геймдеве называют возможность учиться удаленно. Получать знания и навыки в таком формате можно, например, на онлайн-курсах Skillbox. А школьники могут онлайн проходить тематические курсы в «Алгоритмике» и GeekSchool.

Российская индустрия игр активно развивается. После снижения темпов роста, связанного с эффектом высокой базы на фоне локдауна в 2020 году, уже в 2022 году эксперты ожидают их возвращения к двузначным показателям. Это заставляет надеяться на появление новых качественных проектов. И тем, кто хочет быть причастным к их созданию, стоит делать шаги в направлении желанной карьеры уже сейчас. Конкуренция обещает быть высокой.

  • Претворяться в жизнь как пишется
  • Претенденты борются как пишется
  • Претворяешься или притворяешься как пишется
  • Претвориться в жизнь как пишется
  • Претворить мечты в реальность как пишется