Здравствуйте, Максим2006, Вы писали:
М>Было бы лучше иметь два разных типа — один для модульной арифметики, а второй — для беззнаковой (с UB при выходе за границы и иными правилами преобразования)
У меня, если честно, другие предпочтнеия.
Я бы предпочёл, чтобы в C++ был какой-то такой тип int, который вёл бы себя понятно и переносимо. В том числе и при делении отрицательных чисел и при переполнеии и т. п.
Ну и было бы два низкоуровневых урода, для трюков с битами и оптимизацией. Одни -- беззнаковое число, поддерживаемое аппаратурой, а другой -- знаковое поддерживаемое аппаратурой
Вот в C почти так, а в С++ от чего-то упорствуют
Собственно какой есть круг проблем вообще?
1) аппаратура слишком разнообразнео поддерживает отрицательные числа
2) аппаратура слишком по разному ведёт себя при делении отрицательных чисел
3) аппаратура поддерживает такую "беззанковую" арефметику, какую поддерживает. ("Беззанковая" в кавычках, потому, что она реально вообще арифметика по модулю какой-то степени двойки)
4) аппаратура слишком по-разному ведёт себя при сдвигах отрицательных чисел
5) аппаратура слишком по разному ведёт себя при попытках интерпретировать слишком большие беззнаковые числа как знаковые.
Вроде бы всё?
Теперь смотрим что бы мы хотели
1) Доступ к удобному и переносимому целому числу. Чему-то вроде float или double. Хотелось бы предсказуемого и переносимого поведения
2) Доступ к возможностям аппаратуры, для целей трюков с битами и оптимизации.
3) Возможность оптимизации всего этого дела транслятором.
4) Возможность писать простые всякие целочисленные выражения, в которых нет опасности переполнения без всякого размышления о поведении системы в случае переполнения (как мы это делаем с double), ну или, как компромис, с простыми пердусловиями какими-нибудь
Если к делу подходить так, то из имеющихся в современном С++ возможностей выбор не велик
1) Для операция с просто числами использовать int, или свой "безопасный тип", но обычно это не нужно, так как это паранойа.
2) Для трюклв с битами использовать unsigned, как более специфицированный.
3) В любом случае избегать деления и сдвигов отрицательных чисел, даже если тип signеd
Ну нету в C++ удобных средств для этих операций. Ну приходится жить с тем, что имеем. К счастью эти операции очень редко нужны.
4) Если хочется сказать, что метод CArray::Size() возвращает неотрицательные числа, то можно написать комментарий. Так же можно поступить. если он возвращает, напимер, целые числа и т. д.
ИМХО и понятнее и непредсказуемых последситвий намного меньше
С уважением.
Возможно суть спора состоит в том, что участники по разному понимают слово unsigned.
АФАИК в С++ это слово обозначает "арифметика по модулю какой-то определённой степени двойки"
Вроде как приверженцы unsigned размеров массивов не спорят с такой семантикой unsigned типов в С++.
Но от чего-то думают наглядным обозначать этим своеобразным ключевым словом величины, которые не могут быть отрицательными по семантике
ИМХО это так же логично, как обозначать, например, словом auto переменные, которые имеют отношение к автомобилям
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, Аноним, Вы писали:
А>"Игривость" твоих сообщений и "простота" в общении уже несколько запарили. Если ты хорошо знаешь С/С++, то знаешь, что есть определенные гарантии для целочисленных типов. Переносимые программы на С/С++ вполне успешно пишутся, наверное потому, что люди их пишут а не тратят время на флейм о кошмарном ужасе беззнаковых.
Про "кошмарный ужас беззнаковых" я не соглашусь
Но вот о меня напримр тут пытаются убедить, что unsigned типы удобнее, лучше и надёжнее знаковых. Например в задаче итерации массива. Приводят самые разные аргументы. Почти все мне не понятны
С скажу так:
Для работы с числами unsigned типы неудобны.
Есть три ситуации. Третья редкая
1) Мне надо работать с целыми числами. При этом диапазон этих чисел таков, что можно найти такой целый тип, что опасность переполнения незначительна. Тогжа конечно нужно использовать знаковый целый.
2) Мне надо работать с битами или каким-то побитовыми штуками. Скажем с младшими разрядами длинного числа или со словом флагов. Тогда нужно использовать unsigned типы.
3) Не то не другое. Обычно это 1, но числа слишком большие. Хотя и не так. Тогда всё плохо. Разработка удорожается, код становится трудно поддерживаемым, дорогим и непонятным. Лучше бы научиться такой ситуации избегать. Например пререйти к double или ещё что-то придумать
Вот вся критика этой очень прагматичной схемы носит, КМК, совершенно идеологический, а не прагматический характер.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, saproj, Вы писали:
S>Ну вы, надеюсь, делаете проверку ошибок выделения памяти, чтобы программа хоть завершилась штатно, а не упала?
Ну ошибки нехватки памяи в вопросе итерации массива задом наперёд, ИМХО, немного левые
но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения.
при этом стабильно работаем не только на таких либеральных к нехватке памяти платформах, как Win32 и Linux, но и на таких сложных, как Mac OS Classic, скажем
S>На остальное отвечать не буду, т.к. ваш тон не нравится.
За тон прости. Но что-то тут меня чморят все, а на простые вопросы отвечают только три мысли
1) unsigned индексы хорошо, так как они такие же неудобные, как итераторы. поэтому не разбалуешься.
2) Есть лишний бит, и можно съэкономить на проверке x >= 0
3) Это даёт читателю кода информацию, что значение не может быть только неотрицательным.
Мне все три мысли кажутся странными
1) ИМХО это плохое свойство итераторв из STL, а не знаковых типов
2) Обе выгоды плохие. Если уж есть возможность переполнения, то надо писать иначе, чем просто при программировании простых целочисленных формул
3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
E>Если к делу подходить так, то из имеющихся в современном С++ возможностей выбор не велик E>1) Для операция с просто числами использовать int, или свой "безопасный тип". Правда обычно и без специаольного "безопасного целого"удаётся обойтись, так как и с int уже терпимо, хотя конечно и геморно. E>2) Для трюклв с битами использовать unsigned, как более специфицированный. E>3) В любом случае избегать деления и сдвигов отрицательных чисел, даже если тип signеd E>Ну нету в C++ удобных средств для этих операций. Ну приходится жить с тем, что имеем. К счастью эти операции очень редко нужны. E>4) Если хочется сказать, что метод CArray::Size() возвращает неотрицательные числа, то можно написать комментарий. Так же можно поступить. если он возвращает, напимер, чётные числа и т. д. E>ИМХО и понятнее и непредсказуемых последситвий намного меньше
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Максим2006, Вы писали:
М>Предлагаю послушать старейшин... (Б.Стр-п, 2005)
Советы "старейшин" обычно обладают рядом свойств, который надо иметь в виду. Во-первых, "старейшин" много: одни советуют одно, другие — другое (как известно, "старейшина" С (Керниган, кажется) считал модификатор 'const' бесполезным). Во-вторых, эти советы могут отличаться (зачастую — до наоборот) в зависимости от целевой аудитории: новичкам правильнее посоветовать одно, опытным программистам — другое. В-третьих, те же самые старейшины имеют свойство менять свое мнение: вчера они считали так, сегодня — эдак, а завтра — еще как-нибудь. В-четвертых, есть "старейшины"-теоретики, а есть "старейшины"-практики и их советы могут существенно отличаться (я, кстати, никак не подразумеваю, что советы "практиков" ценнее советов "теоретиков"). И т.д.
В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...
Best regards,
Андрей Тарасевич
Re[21]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, Erop, Вы писали:
S>>Ну вы, надеюсь, делаете проверку ошибок выделения памяти, чтобы программа хоть завершилась штатно, а не упала? E>Ну ошибки нехватки памяи в вопросе итерации массива задом наперёд, ИМХО, немного левые
Выбрось итерацию массива из головы . Я не писал ни о каких массивах.
E>но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения.
Хорошо, пусть бросаете исключения. Я под проверкой понимал любую обработку нехватки памяти.
Предлагаю также бросать ваше любимое исключение, если труженик Вася сделал столько деталей, что их количество больше чем numeric_limits<используемый беззнаковый тип>::max(). Это нужно делать не везде, а только в тех местах кода, где математически не доказана невозможность переполнения.
E>3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых
А как же программистская мудрость что, если код нуждается в комментарии, значит его нужно переписать/изменить, чтобы он стал понятнее?
Использование знакового типа для количества произведенных Васей деталей — это по-моему уменьшение понятности кода.
spine! А как можно не согласиться с нижеследующим вопросом?
E>А вот ради чего?
Я не то, чтобы против, просто интеренсно понять логику собеседника
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, saproj, Вы писали:
E>>но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения. S>Хорошо, пусть бросаете исключения. Я под проверкой понимал любую обработку нехватки памяти. S>Предлагаю также бросать ваше любимое исключение, если труженик Вася сделал столько деталей, что их количество больше чем numeric_limits<используемый беззнаковый тип>::max(). Это нужно делать не везде, а только в тех местах кода, где математически не доказана невозможность переполнения.
А толку-то?
Вот, если продолжать аналогию с памятью и её нехватками, то если на платформе её хватает, то всё хорошо, если не хватет, то я беру руки в ноги и налаживаю и оптимизирую, пока не хватит. А что делать с Васей, кторый наваял деталей столько что в unsigned int не лезет?
Тоже настраивать и оптимизировать и переписывать?
Ну дык тогда limits ничем нам не помог! Что так переписывать, что сяк переписывать
E>>3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых S>А как же программистская мудрость что, если код нуждается в комментарии, значит его нужно переписать/изменить, чтобы он стал понятнее? S>Использование знакового типа для количества произведенных Васей деталей — это по-моему уменьшение понятности кода.
Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"?
ОТветит мне кто-то на этот "простой" вопрос или нет?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...
Итак. "Тараскевич vs Страуструп" -- куму поверим?
Страуструп пишет, что типа вот, опыт показывает, что нехорошо выходит с unsigned-то. В целом более или менее убедительно.
Типа бит завоёванный всё равно не спасает, а гарантий unsigmed никаких не даёт из-за парвил преобразования типов в С++.
И правда же вроде оба суждения классика
А что же говорит нам уважаемый Андрей?
Что unsigned индексы массивов таки понятнее?
Что unsigned таки гарантирует беззнаковость значения?
Что переполнения не избежать по любому, так что всё время надо писать код, который корректно работает в условиях переполнения и всюду на него закладываться?
или я что-то таки недопонял?
Я понимаю, что моя скромная персона не пользуеться уваженим, среди экспертов, но старик-то Срауструп может заслужил аргументированых возражений на свои соображения, а не довольно содержательных рассуждений на тему о том, что он и сам может уже передумал, да и может он это не для вас писал а для кого-то ещё и т. д.
В любом случае в мире, где живу я, идеии сильнее людей. Так что даже если Бьярн и передумал, аргументация-то его осталась
или это он всё писал для секретарш иногда применяющих С++ для своих нужд, а не для сверхкрутых перцев с КЫВТ/С++?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Максим2006, Вы писали:
М>Было бы лучше иметь два разных типа — один для модульной арифметики, а второй — для беззнаковой (с UB при выходе за границы и иными правилами преобразования)
Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.
Перекуём баги на фичи!
Re[23]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, saproj, Вы писали:
E>>>но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения. S>>Хорошо, пусть бросаете исключения. Я под проверкой понимал любую обработку нехватки памяти. S>>Предлагаю также бросать ваше любимое исключение, если труженик Вася сделал столько деталей, что их количество больше чем numeric_limits<используемый беззнаковый тип>::max(). Это нужно делать не везде, а только в тех местах кода, где математически не доказана невозможность переполнения.
E>А толку-то? E>Вот, если продолжать аналогию с памятью и её нехватками, то если на платформе её хватает, то всё хорошо, если не хватет, то я беру руки в ноги и налаживаю и оптимизирую, пока не хватит. А что делать с Васей, кторый наваял деталей столько что в unsigned int не лезет?
Ответ очень простой: перейти на uint64_t. Не надо препятствовать трудовым подвигам.
E>>>3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых S>>А как же программистская мудрость что, если код нуждается в комментарии, значит его нужно переписать/изменить, чтобы он стал понятнее? S>>Использование знакового типа для количества произведенных Васей деталей — это по-моему уменьшение понятности кода.
E>Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"? E>ОТветит мне кто-то на этот "простой" вопрос или нет?
В случае с количеством деталей арифметика по модулю нам вряд ли нужна, мы просто не будем допускать превышения. (Разве что для более удобной проверки из примера 2 отсюда
Здравствуйте, Erop, Вы писали:
АТ>>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...
E>Итак. "Тарасевич vs Страуструп" -- куму поверим?
О, смотрите-ка! Несколько сообщений назад товарищ Erop вынес в заголовок своего сообщения фразу "А ты кто такой?", тем самым подразумевая, что я якобы сказал ему что-то подобное. На самом деле ничего подобно я ему тогда не говорил, в чем несложно убедиться, перечитав мое сооветствующее сообщение. Т.е. товарищ Erop просто решил немножко наврать, рассчитывая на то, что в такой большой дискуссии какие-то пользователи ограничаться "чтением заголовков" не вникая в суть.
А вот здесь мы наблюдаем соврешенно явное и неприкрытое то самое "А ты кто такой?". И исходит оно от кого? Правильно — от того самого Erop-а! И самое интересное, что опять же мы имеем случай того же самого вранья. И опять же это вранье вынесено в заголовок сообщения. В то время как никакого "Тарасевич vs Страуструп" в моем сообщении и близко не содержится.
Набивший оскомину (мне, по крайней мере) пример: мы все прекрасно знаем (или, по крайней мере, многие из нас), что, например, в известной книге по С++ того же Страуструпа содержатся заведомо ошибочные утверждения, типа утверждения о наличии конструктора у целочисленных типов. Более того, Страутруп сам прекрасно знает, что это утверждение ошибочно. И все прекрасно понятно, почему эта умышленная "ошибка" сделана. Когда я (например — я), утверждаю, что это утвержддение ошибочно, никакого "Тарасевич vs Страуструп" подтекста в таком утверждении нет. Тем не менее, когда этот вопрос возникает в обсуждении, почти всегда надется горлопан, который начнет орать что-то на тему "Тарасевич vs Страуструп". Дешево и предсказуемо. Но зачем — непонятно.
E>Страуструп пишет, что типа вот, опыт показывает, что нехорошо выходит с unsigned-то. В целом более или менее убедительно.
Тем не менее, комитет по стандартизации языка С++ решил, что активное использование беззнаковых типов в STL приемлемо. Там, наверное, одни "Тарасевичи" сидят...
E>А что же говорит нам уважаемый Андрей? E>Что unsigned индексы массивов таки понятнее?
Разумеется. Кстати, никак не противоречит Страуструпу.
E>Что unsigned таки гарантирует беззнаковость значения?
Разумеется. А это откуда взялось? Что, кто-то говорит, что не гарантирует? Страуструп, может быть?
E>Что переполнения не избежать по любому, так что всё время надо писать код, который корректно работает в условиях переполнения и всюду на него закладываться?
Передернуто. Не "переполнения не избежать", а "опасности переполнения не избежать". Кстати, опять никак не противоречит Страуструпу.
E>или я что-то таки недопонял?
А Вы и не пытаетесь понять. Вы занимаетесь флеймом. Многим это было очевидно и раньше, но сейчас это уже, я уверен, очевидно всем.
Мне, например, было соврешено очевидно, что ответ от Erop мое последнее сообщение будет написан на тему "Тарасевич vs Страуструп".
E>но старик-то Срауструп может заслужил аргументированых возражений на свои соображения,
Возражений тут целая дискуссия. Зачем повторять их снова?
E>или это он всё писал для секретарш иногда применяющих С++ для своих нужд, а не для сверхкрутых перцев с КЫВТ/С++?
Ну если дла Вас мир делится только на "секретарш" и "сверхкрутых перцев", то, как говорится, ту уж ничего не попишешь...
Здравствуйте, Erop, Вы писали:
АТ>>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...
E>Итак. "Тараскевич vs Страуструп" -- куму поверим? E>Страуструп пишет, что типа вот, опыт показывает, что нехорошо выходит с unsigned-то. В целом более или менее убедительно.
Не хотелось влезать в вашу милую беседу, однако давайте будем уважать оппонентов.
Один раз возможно опечатка, но два уже тенденция Не стоит.
По поводу Страуструпа. Если бы все было так однозначно, то vector::size_type был бы интом.
Re[24]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, saproj, Вы писали:
E>>Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"? E>>ОТветит мне кто-то на этот "простой" вопрос или нет?
S>В случае с количеством деталей арифметика по модулю нам вряд ли нужна, мы просто не будем допускать превышения. (Разве что для более удобной проверки из примера 2 отсюда
Ну дык и знаковую мы тем более не переполним
Так всё-таки ответ на вопрос "почему лучше" будет каким? )
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Erlond, Вы писали:
E>>Строго говоря — да, но если разница между двумя unsigned превышает INT_MAX, то должно работать, или я не прав? E>Нифига не так. E>Предатавь себе, что знаковые числа хранятся в виде мантисы и знака, например
Не представляю. При чем тут это? Мы рассмотриваем сечас int и unsigned int.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Максим2006, Вы писали:
К>Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.
Да плохо она справляется.
Например, как всё-таки вычислить корректно разность двух unsigned чисел, ессли больше может быть любое?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erlond, Вы писали:
E>>Предатавь себе, что знаковые числа хранятся в виде мантисы и знака, например E>Не представляю. При чем тут это? Мы рассмотриваем сечас int и unsigned int.
А такие реализации таки бывают
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
"А ты кто такой?" -- это цитата из "Золотого телёнка"
Там перед тем как подраться герои выясняли друг у друга это сокраментальнео знание
Прости если процитировал неузноваемо
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[25]: Нет бы вот ответить ясно, а не пальцами кидаться :)
Здравствуйте, Erop, Вы писали:
E>>>Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"? E>>>ОТветит мне кто-то на этот "простой" вопрос или нет?
S>>В случае с количеством деталей арифметика по модулю нам вряд ли нужна, мы просто не будем допускать превышения. (Разве что для более удобной проверки из примера 2 отсюда
, но это мелочь.)
E>Ну дык и знаковую мы тем более не переполним
Во-первых непонятно почему "тем более".
Во-вторых никто не говорит что со знаковым типом нельзя написать безошибочный код для решения этой же задачи.
E>Так всё-таки ответ на вопрос "почему лучше" будет каким? )
сообщения. Другими людьми тоже сказано не раз. Обрати внимание как терпеливо и подробно объясняет Андрей Тарасевич. Не лишне будет еще раз сосредоточенно прочитать.
Решил добавить от себя немного.
Когда мне надо использовать с одной стороны беззнаковай инт как самый близкий для хранения неотрицательных значений (к примеру, размер массива), с другой, знаковай для проверки на выход за диапазон (assert(m_nSize>=0)), — использую такой тип:
#ifdef _DEBUG
typedef int MYLIB_SIZE;
#else
typedef unsigned int MYLIB_SIZE;
#endif
void foo(MYLIB_SIZE size) {
assert(size >= 0);
}
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]