Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.07.23 16:18
Оценка:
Здравствуйте!

Я тут решил немного пошмыгать.

Начитался тут тем про MSVC /Wall /WX, и решил тоже попробовать.

Повылезала куча всего, но в основном signed/unsigned mismatch, и вот это вот всё. Индексы в массивах и векторах — хочет size_t, а у меня часто int. Или исторически так сложилось, или требования какого-то API, или просто было пофигу, потому что я знаю, что у меня массив вообще никогда не вырастет до такого размера, чтобы знаковый бит стал проблемой (например, вектор из созданных HPEN/HBRUSH — система ляжет раньше, чем я только начну приближаться к проблемному размеру), и, часто, при этом, этот индекс если меньше нуля, то это инвалидный индекс, и я всегда проверяю инвалидность. Или битовые операторы и операторы сдвига — они, как оказалось, возвращают int/int64, а не тот тип, который изначально участвует в выражении. Полечил сишными кастами. Если бы лечить static_cast'ами, это каждое выражение становится пипец каким ужасным и нечитаемыми.

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

Почему сишным кастом пользоваться плохо?

Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:
auto u = (unsigned)(std::uint8_t)ch;


Но можно и так:
auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));


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

Припоминаю аргументы:
1) Удобно искать cast'ы — но если на каждый чих их использовать, то любой поиск выдаст тонно-километры этих кастов. А если мы знаем точно, к какому типу ищем каст, то не всё ли равно, что искать — либо "_cast<TYPE>(", либо "(TYPE)"?
2) Сишный каст универсален, и беспринципно беспощаден — ну это есть, да, надо думать иногда, стоит ли использовать сишный каст или в узком месте использовать специализированный плюсовый каст. Может, просто стоит в код стайлах писать, в каких случаях надо использовать плюсовые касты, подразумевая, что в остальных случаях можно обойтись сишным кастом?

Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)

ОбсудиПохоливарим?
Маньяк Робокряк колесит по городу
Re: Сишный каст - зло?
От: reversecode google
Дата: 27.07.23 17:32
Оценка: :)
вот они последователи шмыги, которые ни разу не бывали на собеседованиях
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.07.23 18:33
Оценка:
Здравствуйте, reversecode, Вы писали:

R>вот они последователи шмыги, которые ни разу не бывали на собеседованиях


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

Да, даже в НИИ в код стайле было прописано использование строго только плюсовых кастов. И нигде я не видел внятных обоснований для этого.


ЗЫ А ты зачем Шмыгу обижаешь, твой же побратим, не?
Маньяк Робокряк колесит по городу
Re[3]: Сишный каст - зло?
От: reversecode google
Дата: 27.07.23 18:46
Оценка:
расскажите когда побываете на С++ собеседовании

хотя вряд ли вы его пройдете

сможете вместе со шмыгой добивать очередной С++++++++ проект
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.07.23 18:56
Оценка:
Здравствуйте, reversecode, Вы писали:

R>вот они последователи шмыги, которые ни разу не бывали на собеседованиях


Кстати, ты бы мог, как сознательный украинец, взять шмыгу под свой патронаж, помочь побратиму, а заодно вы бы схлопнулись и аннигилировали, как частица и античастица, очистив профильные форумы от своего присутствия
Маньяк Робокряк колесит по городу
Re[4]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.07.23 19:00
Оценка:
Здравствуйте, reversecode, Вы писали:

R>расскажите когда побываете на С++ собеседовании


Я прошел много собесов, яндексовые были не самые сложные


R>хотя вряд ли вы его пройдете


Это у тебя желчь разливается, от того, что сам никуда не смог пройти?


R>сможете вместе со шмыгой добивать очередной С++++++++ проект


анигилируйся лучше со шмыгой, всем всяко лучше будет, чем политоту тащить в профильный форум
Маньяк Робокряк колесит по городу
Re[3]: Сишный каст - зло?
От: reversecode google
Дата: 27.07.23 19:05
Оценка:
считаю надо зреть в корень, правда ?
учитывая что женская днк у всех присутствующих на форуме общая

поэтому все тоже самое со шмыгой можете проделать и вы
Re[4]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.07.23 19:35
Оценка:
Здравствуйте, reversecode, Вы писали:

R>поэтому все тоже самое со шмыгой можете проделать и вы


Это твой побратим

ЗЫ Модераторы, снесите плс эту подветку в политоту
Маньяк Робокряк колесит по городу
Re: Сишный каст - зло?
От: Pzz Россия https://github.com/alexpevzner
Дата: 27.07.23 20:18
Оценка: +2
Здравствуйте, Marty, Вы писали:

M>Почему сишным кастом пользоваться плохо?


Потому, что grep static_cast сказать можно, а в случае сишного каста грепать нечего.

Но это не очень сильный аргумент IMHO
Re: Сишный каст - зло?
От: T4r4sB Россия  
Дата: 27.07.23 21:39
Оценка: 9 (1)
Здравствуйте, Marty, Вы писали:

M> Индексы в массивах и векторах — хочет size_t, а у меня часто int. Или исторически так сложилось, или требования какого-то API, или просто было пофигу, потому что я знаю, что у меня массив вообще никогда не вырастет до такого размера, чтобы знаковый бит стал проблемой (например, вектор из созданных HPEN/HBRUSH — система ляжет раньше, чем я только начну приближаться к проблемному размеру), и, часто, при этом, этот индекс если меньше нуля, то это инвалидный индекс, и я всегда проверяю инвалидность.


Добро пожаловать в клуб
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1428r0.pdf
Re: Сишный каст - зло?
От: andyp  
Дата: 27.07.23 23:18
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>ОбсудиПохоливарим?


За использование static_cast:
1. Пастухи джунов и языковые пуристы тебя сожрут
2. Тебе платят за набранные буквы



Уж для integral conversions я использую сишный каст, меньше писать и ничем имхо не опаснее чем static_cast.
Re: Сишный каст - зло?
От: Alekzander  
Дата: 28.07.23 04:44
Оценка:
Здравствуйте, Marty, Вы писали:

M>Например, я убираю возможную знаковость у char переменной


Для чего? Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование.

Если я правильно понял, тебе лень нормально написать bound checking, и ты заменил его кастами.

M>ОбсудиПохоливарим?


Я следую прямо противоположному правилу: кроме сишных кастов ничего не использовать, чтобы было меньше говнокода. Логика очень простая и железобетонная: ЛЮБОЙ КАСТ ЭТО СИТУАЦИЯ, КОГДА *ТЫ* ЗНАЕШЬ О НАСТОЯЩЕМ ТИПЕ, А КОМПИЛЯТОР — ПОЧЕМУ-ТО НЕТ. Таких ситуаций надо избегать, потому, что они говорят о неправильной архитектуре и/или неверно написанном коде. Есть, конечно, ситуации, когда имеешь дело с историческими артефактами типа WinAPI, но там и Си-каста хватает.
Отредактировано 28.07.2023 5:13 Alekzander . Предыдущая версия . Еще …
Отредактировано 28.07.2023 4:50 Alekzander . Предыдущая версия .
Re[2]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 05:17
Оценка: +1
Здравствуйте, Alekzander, Вы писали:

A>Здравствуйте, Marty, Вы писали:


M>>Например, я убираю возможную знаковость у char переменной


A>Для чего? Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование.


A>Если я правильно понял, тебе лень нормально написать bound checking, и ты заменил его кастами.


Бывают случаи, когда бинарные данные приходят тупо в виде const char* или std::string, а собрать их нужно, скажем, в std::vector<std::uint8_t>. Повлиять на источник данных нельзя, это может быть сторонняя библиотека или кусок кода, написанный 100500 лет назад.
Re: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 05:24
Оценка: +2 -2
Здравствуйте, Marty, Вы писали:

M>ОбсудиПохоливарим?


За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности).

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

И нечего тут холиварить.
Re: Сишный каст - зло?
От: Maniacal Россия  
Дата: 28.07.23 06:40
Оценка:
Здравствуйте, Marty, Вы писали:

M>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:

M>
M>auto u = (unsigned)(std::uint8_t)ch;
M>


Achtung! unsigned это unsigned int, а не unsigned char. Тут один байт в четыре превращается.

M>Но можно и так:

M>
M>auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
M>


static_cast, dynamic_cast, reinterpret_cast это в первую очередь инструменты для преобразования указателей базовых классов в унаследованные с контролем или в случае reinterpret_cast явное указание, что не в наследуемый.
Хотя в рекомендациях пишут, что static_cast можно и нужно использовать даже для встроенных типов.
Re[2]: Сишный каст - зло?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 28.07.23 11:07
Оценка: +1
Здравствуйте, so5team, Вы писали:

S>За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности).

Евангелизм как он есть.
Sic luceat lux!
Re[3]: Сишный каст - зло?
От: Alekzander  
Дата: 28.07.23 11:10
Оценка:
Здравствуйте, so5team, Вы писали:

M>>>Например, я убираю возможную знаковость у char переменной


A>>Для чего? Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование.


A>>Если я правильно понял, тебе лень нормально написать bound checking, и ты заменил его кастами.


S>Бывают случаи, когда бинарные данные приходят тупо в виде const char* или std::string, а собрать их нужно, скажем, в std::vector<std::uint8_t>. Повлиять на источник данных нельзя, это может быть сторонняя библиотека или кусок кода, написанный 100500 лет назад.


Я же написал, что иногда приходится иметь дело с историческими артефактами, но там и Си-каста хватает. Речь идёт о том, что всё, что сложнее, лично для меня детектор.
Re[3]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 11:29
Оценка: +4 -2
Здравствуйте, Kernan, Вы писали:

S>>За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности).

K>Евангелизм как он есть.

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

Далеко не глупые люди посмотрели к тему приводит C-шный каст, внедрили в C++ специальные конструкции, которые если не делают код безопаснее, то уж точно явно отмечают подозрительные места... Но нет, всегда есть кто-то шибко умный, который скажет, что у него-то уж точно все нормально.
Re[4]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 11:32
Оценка: +2 -1
Здравствуйте, Alekzander, Вы писали:

A>Я же написал, что иногда приходится иметь дело с историческими артефактами, но там и Си-каста хватает.


Си-каст? Прострелить ноги, оторвать руки и на мороз шагом марш!

Но вообще, конечно, забавно. Сперва рассуждения о "Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование", а потом бах, и Си-каст, который на все типопреобразования кладет с прибором. Вот что в головах у людей?
Re[4]: Сишный каст - зло?
От: sergii.p  
Дата: 28.07.23 11:37
Оценка: +2
Здравствуйте, so5team, Вы писали:

S>Далеко не глупые люди посмотрели к тему приводит C-шный каст, внедрили в C++ специальные конструкции, которые если не делают код безопаснее, то уж точно явно отмечают подозрительные места...


тут вопрос как раз о конструкциях, которые приводят к простреленным конечностям с C и C++ кастом. Я вот как-то придумать такие конструкции с ходу не могу.
Просто "пометить подозрительные места" — мне кажется слишком слабый аргумент для ввода 4 новых слов в язык.
Re: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 28.07.23 11:43
Оценка:
Здравствуйте, Marty, Вы писали:

M>Припоминаю аргументы:

M>1) Удобно искать cast'ы — но если на каждый чих их использовать, то любой поиск выдаст тонно-километры этих кастов. А если мы знаем точно, к какому типу ищем каст, то не всё ли равно, что искать — либо "_cast<TYPE>(", либо "(TYPE)"?
M>2) Сишный каст универсален, и беспринципно беспощаден — ну это есть, да, надо думать иногда, стоит ли использовать сишный каст или в узком месте использовать специализированный плюсовый каст. Может, просто стоит в код стайлах писать, в каких случаях надо использовать плюсовые касты, подразумевая, что в остальных случаях можно обойтись сишным кастом?

Видишь, ты и сам всё знаешь.

M>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


M>ОбсудиПохоливарим?


Ну если не обсуждать, что у C|C++ вообще надо менять не кран, а всю систему, то обсуждать и нечего
The God is real, unless declared integer.
Re[5]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 12:02
Оценка: 4 (2) +3 -1
Здравствуйте, sergii.p, Вы писали:

S>>Далеко не глупые люди посмотрели к тему приводит C-шный каст, внедрили в C++ специальные конструкции, которые если не делают код безопаснее, то уж точно явно отмечают подозрительные места...


SP>тут вопрос как раз о конструкциях, которые приводят к простреленным конечностям с C и C++ кастом. Я вот как-то придумать такие конструкции с ходу не могу.

SP>Просто "пометить подозрительные места" — мне кажется слишком слабый аргумент для ввода 4 новых слов в язык.

У меня нет под рукой собственной ошибки (хотя компилятор несколько раз в год бьет по рукам в попытках неправильно использовать static_cast, особенно в обобщенном коде). Но вот хороший пример из Интернета:
#include <iostream>
using namespace std;
 
class Base
{};
 
class Derived: private Base
{
  // Inherited private/protected
  // not public
};
 
// Driver code
int main()
{   
  Derived d1;
   
  // C-style cast allowed
  Base* b1 = (Base*)(&d1);
   
  // static_cast not allowed
  Base* b2 = static_cast<Base*>(&d1);
  return 0;
}
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 12:35
Оценка:
Здравствуйте, Pzz, Вы писали:

M>>Почему сишным кастом пользоваться плохо?


Pzz>Потому, что grep static_cast сказать можно, а в случае сишного каста грепать нечего.


Pzz>Но это не очень сильный аргумент IMHO



Вот и я про что. Ну, grep static_cast, и что? Оно выдаст килотонны этих кастов, и накуя это нужно? А каст к конкретному типу можно и в случае сишного каста найти
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 12:41
Оценка: +1
Здравствуйте, so5team, Вы писали:

M>>ОбсудиПохоливарим?


S>За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности).


S>Любителям оправдываться по типу "ну тут же все очевидно и так проще, да и писать меньше" для лучшего усвоения еще и ноги прострелить.


S>И нечего тут холиварить.


Я так понимаю, аргументов не будет, ты сразу на расстрел отводишь за такие вопросы?
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 12:45
Оценка: +2 -1
Здравствуйте, Maniacal, Вы писали:

M>>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:

M>>
M>>auto u = (unsigned)(std::uint8_t)ch;
M>>


M>Achtung! unsigned это unsigned int, а не unsigned char. Тут один байт в четыре превращается.


Спасибо, кэп, я в курсе. Поэтому я сначала кастую к unsigned типу той же размерности, и только потом к unsigned int'у


M>static_cast, dynamic_cast, reinterpret_cast это в первую очередь инструменты для преобразования указателей базовых классов в унаследованные с контролем или в случае reinterpret_cast явное указание, что не в наследуемый.

M>Хотя в рекомендациях пишут, что static_cast можно и нужно использовать даже для встроенных типов.

И я вот как раз про это. Плюсовые касты — это сигнал, что происходит какое-то нетривиальное преобразование. Что бывает достаточно редко. В остальных случаях достаточно сишного каста
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 12:46
Оценка: +1
Здравствуйте, netch80, Вы писали:

M>>Припоминаю аргументы:

M>>1) Удобно искать cast'ы — но если на каждый чих их использовать, то любой поиск выдаст тонно-километры этих кастов. А если мы знаем точно, к какому типу ищем каст, то не всё ли равно, что искать — либо "_cast<TYPE>(", либо "(TYPE)"?
M>>2) Сишный каст универсален, и беспринципно беспощаден — ну это есть, да, надо думать иногда, стоит ли использовать сишный каст или в узком месте использовать специализированный плюсовый каст. Может, просто стоит в код стайлах писать, в каких случаях надо использовать плюсовые касты, подразумевая, что в остальных случаях можно обойтись сишным кастом?

N>Видишь, ты и сам всё знаешь.


Это довольно спорные аргументы


M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


M>>ОбсудиПохоливарим?


N>Ну если не обсуждать, что у C|C++ вообще надо менять не кран, а всю систему, то обсуждать и нечего


Ну, если тебе не нравится C++, может, тебе просто сменить язык, а не пытаться менять язык?
Маньяк Робокряк колесит по городу
Re[4]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 12:50
Оценка:
Здравствуйте, so5team, Вы писали:

S>>>За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности).

K>>Евангелизм как он есть.

S>Или слишком много набитых в C++ шишек, которых можно было бы избежать, если бы программисты думали о том, как написать нормальный код, а не о том, чтобы сэкономить несколько символов.


S>Далеко не глупые люди посмотрели к тему приводит C-шный каст, внедрили в C++ специальные конструкции, которые если не делают код безопаснее, то уж точно явно отмечают подозрительные места... Но нет, всегда есть кто-то шибко умный, который скажет, что у него-то уж точно все нормально.



У меня очень, очень много рабочего кода, написанного с сишными кастами. В том числе коммерческий (был, сейчас скис, спрос упал) проект, и плагин к Far'у. И это всё как-то работает
Маньяк Робокряк колесит по городу
Re[3]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 12:51
Оценка: +1 -1
Здравствуйте, Marty, Вы писали:

M>Я так понимаю, аргументов не будет, ты сразу на расстрел отводишь за такие вопросы?


Все аргументы уже многократно были высказаны множеством людей во множестве мест. Кто до сих пор не внял -- на экзекуцию.

PS. Ну какой наброс, такие и последствия.
Re[5]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 12:53
Оценка: +3
Здравствуйте, Marty, Вы писали:

M>У меня очень, очень много рабочего кода, написанного с сишными кастами. В том числе коммерческий (был, сейчас скис, спрос упал) проект, и плагин к Far'у. И это всё как-то работает


Ошибка выжившего.
Re[6]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 12:54
Оценка: -2
Здравствуйте, so5team, Вы писали:


S>У меня нет под рукой собственной ошибки (хотя компилятор несколько раз в год бьет по рукам в попытках неправильно использовать static_cast, особенно в обобщенном коде). Но вот хороший пример из Интернета:

S>
S>#include <iostream>
S>using namespace std;
 
S>class Base
S>{};
 
S>class Derived: private Base
S>{
S>  // Inherited private/protected
S>  // not public
S>};
 
S>// Driver code
S>int main()
S>{   
S>  Derived d1;
   
S>  // C-style cast allowed
S>  Base* b1 = (Base*)(&d1);
   
S>  // static_cast not allowed
S>  Base* b2 = static_cast<Base*>(&d1);
S>  return 0;
S>}



Это как раз тот редкий случай, когда плюсовый каст нужен. Но у меня на один такой случай есть ещё 99 случаев, когда плюсовый каст не нужен. И я не вижу смысла засирать код плюсовыми кастами, потому что, когда надо будет, проблемные места будет не найти и-за того, что плюсовые касты использовались на каждый чих
Маньяк Робокряк колесит по городу
Re[4]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 13:02
Оценка:
Здравствуйте, so5team, Вы писали:

M>>Я так понимаю, аргументов не будет, ты сразу на расстрел отводишь за такие вопросы?


S>Все аргументы уже многократно были высказаны множеством людей во множестве мест. Кто до сих пор не внял -- на экзекуцию.


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


S>PS. Ну какой наброс, такие и последствия.


Да нет, Ты уже которое сообщение изворачиваешься, ничего конкретного не сказав
Маньяк Робокряк колесит по городу
Re[6]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 13:05
Оценка: +1 -2
Здравствуйте, so5team, Вы писали:

M>>У меня очень, очень много рабочего кода, написанного с сишными кастами. В том числе коммерческий (был, сейчас скис, спрос упал) проект, и плагин к Far'у. И это всё как-то работает


S>Ошибка выжившего.


Аргументов не будет, ясно
Маньяк Робокряк колесит по городу
Re[5]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 13:11
Оценка: +2
Здравствуйте, Marty, Вы писали:

M>Понимаю, тебе просто западло привести их ещё раз. Или, может, ты боишься их приводить, чтобы они не были разбиты за явной несостоятельностью, ведь это бы ударило и по тебе, как принесшему их? Да не, бред какой-то


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

Одна из самых паршивых вещей, которая происходит с Си-кастами, это наплевательство на константность. Т.е. сделать вот так:
const char * in = ...;
unsigned char * src = (unsigned char *)in;
...
*src = 0;

можно запросто.
Но даже на reinterpret_cast<unsigned char *>(in) компилятор будет ругаться.

S>>PS. Ну какой наброс, такие и последствия.


M>Да нет, Ты уже которое сообщение изворачиваешься, ничего конкретного не сказав


Кто-то в интернете написал, что можно переходить проезжую часть на красный свет. Когда ему ответили, что таких переходящих можно сразу прямиком на кладбище увозить, он посетовал, что ничего конкретного не говорят, изворачиваются.
Re[6]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 13:16
Оценка:
Здравствуйте, so5team, Вы писали:

S>Одна из самых паршивых вещей, которая происходит с Си-кастами, это наплевательство на константность. Т.е. сделать вот так:

S>
S>const char * in = ...;
S>unsigned char * src = (unsigned char *)in;
S>...
S>*src = 0;
S>

S>можно запросто.

Можно. И что? Можно быстро выпить 10 литров воды и умереть от отравления H2O.


S>Но даже на reinterpret_cast<unsigned char *>(in) компилятор будет ругаться.


А на const_cast — не будет. И?


M>>Да нет, Ты уже которое сообщение изворачиваешься, ничего конкретного не сказав


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


Очередная демагогия
Маньяк Робокряк колесит по городу
Re[7]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 13:31
Оценка: +3 -1
Здравствуйте, Marty, Вы писали:

M>Можно. И что?


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

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

S>>Но даже на reinterpret_cast<unsigned char *>(in) компилятор будет ругаться.


M>А на const_cast — не будет. И?


const_cast вам придется написать явно. И тут есть два сценария, когда вы написали reinterpret_cast без const_cast и получили по рукам от компилятора:

1. Вы не обратили внимания на то, что исходный указатель константный (а может и не знали об этом, если все происходит в обобщенном коде, где какой-нибудь Src_Type может быть как const-указателем, так и не-const). Компилятор указал вам на это и вы поняли, что делаете что-то не то. И меняете либо входящий тип (чтобы он не было константным), либо меняете свой код, чтобы обходиться константным указателем. Либо пишете const_cast и молитесь на отсутствие UB.

2. Вы дописали const_cast не приходя в сознание. Ну хочет компилятор, ну на тебе. В этом случае хотя бы это место будет проще найти, т.к. const_cast-ы быстрее бросаются в глаза да и ищутся проще, чем Си-касты.

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

M>Очередная демагогия


Она тут с самого первого вашего сообщения.
Re[8]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 13:35
Оценка:
Здравствуйте, so5team, Вы писали:

M>>Можно. И что?


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


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


S>>>Но даже на reinterpret_cast<unsigned char *>(in) компилятор будет ругаться.


M>>А на const_cast — не будет. И?


S>const_cast вам придется написать явно. И тут есть два сценария, когда вы написали reinterpret_cast без const_cast и получили по рукам от компилятора:


S>1. Вы не обратили внимания на то, что исходный указатель константный (а может и не знали об этом, если все происходит в обобщенном коде, где какой-нибудь Src_Type может быть как const-указателем, так и не-const). Компилятор указал вам на это и вы поняли, что делаете что-то не то. И меняете либо входящий тип (чтобы он не было константным), либо меняете свой код, чтобы обходиться константным указателем. Либо пишете const_cast и молитесь на отсутствие UB.


S>2. Вы дописали const_cast не приходя в сознание. Ну хочет компилятор, ну на тебе. В этом случае хотя бы это место будет проще найти, т.к. const_cast-ы быстрее бросаются в глаза да и ищутся проще, чем Си-касты.


S>Т.е. даже в худшем случае вы получаете больше бенефитов, чем от Си-каста.


Ты описал ситуацию, которая ровно ноль раз у меня в практике встречалась
Маньяк Робокряк колесит по городу
Re[9]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 13:44
Оценка: +5
Здравствуйте, Marty, Вы писали:

M>Ты описал ситуацию, которая ровно ноль раз у меня в практике встречалась


Так я и говорю: ошибка выжившего.

Но вообще я вот чего понять не могу. Вот есть C++, в котором есть:

static_cast,
const_cast,
dynamic_cast,
reinterpret_cast

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

Но кому-то этого мало, и кто-то допускает в дополнение к этим средствам еще и Си-каст. Причем в стиле: вот тут можно, а вот тут низяя!

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

Ну и вопрос: зачем усложнять себе жизнь?
Re[10]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 13:59
Оценка: :)))
Здравствуйте, so5team, Вы писали:

S>Ну и вопрос: зачем усложнять себе жизнь?


Собери свой проект с /Wall /WX, удивись, сколько варнингов будет в простейших битовых выражениях, расставь там плюсовые касты и попробуй это прочитать
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: _NN_ www.nemerleweb.com
Дата: 28.07.23 14:02
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, Marty, Вы писали:


M>> Индексы в массивах и векторах — хочет size_t, а у меня часто int. Или исторически так сложилось, или требования какого-то API, или просто было пофигу, потому что я знаю, что у меня массив вообще никогда не вырастет до такого размера, чтобы знаковый бит стал проблемой (например, вектор из созданных HPEN/HBRUSH — система ляжет раньше, чем я только начну приближаться к проблемному размеру), и, часто, при этом, этот индекс если меньше нуля, то это инвалидный индекс, и я всегда проверяю инвалидность.


TB>Добро пожаловать в клуб

TB>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1428r0.pdf

Время идёт, а вопросы всё те же
Откуда эта лютая любовь к знаковым целым?
Автор: Евгений Музыченко
Дата: 05.05.20


А вот и решение: gsl::index
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 14:45
Оценка: +1
Здравствуйте, Marty, Вы писали:

S>>Ну и вопрос: зачем усложнять себе жизнь?


M>Собери свой проект с /Wall /WX, удивись, сколько варнингов будет


Спасибо, но мы и так, по возможности, живем с -pedantic -Wall и даже -Weverything, а когда позволяют зависимости, то еще и с -Werror. Но зависимости далеко не всегда такую роскошь позволяют

M>в простейших битовых выражениях,


Во-первых, откуда там?

M>расставь там плюсовые касты и попробуй это прочитать


Во-вторых, если у вас C++ помоложе C++11, то можно же использовать локальные функции. Вот, из реального проекта (комментарии изъяты):
const auto ptr_cast = []( const std::byte * ptr ) -> std::uint8_t * {
        return reinterpret_cast< std::uint8_t * >(
                const_cast< std::byte * >( ptr ) );
    };

fresh_frame->buf[ 0 ] = av_buffer_create(
        ptr_cast( image_bytes ),
        total_memory_size,
        []( void *, std::uint8_t * ) -> void {},
        nullptr,
        AV_BUFFER_FLAG_READONLY );
if( !(fresh_frame->buf[ 0 ]) )
{
    throw std::runtime_error{...};
}

std::size_t plane_index = 0u;
for( const auto plane_size : data_plane_sizes )
{
    fresh_frame->data[ plane_index ] = ptr_cast( image_bytes );
    image_bytes += plane_size;
    ++plane_index;
}
Отредактировано 28.07.2023 14:49 so5team . Предыдущая версия .
Re: Сишный каст - зло?
От: DiPaolo Россия  
Дата: 28.07.23 15:09
Оценка: +3
Сначала отсылка к уважаемым в плюсовом мире людям, Страуструпу и Саттеру:
ES.48: Avoid casts
ES.49: If you must use a cast, use a named cast
ES.50: Don’t cast away const

Советую пройти почитать по ссылкам — там расписано, почему так стоит делать или не делать.

Далее мои мысли. Вот привел so5team привет выше (http://rsdn.org/forum/cpp/8570018.1):
Автор: so5team
Дата: 28.07.23

#include <iostream>
using namespace std;
 
class Base
{};
 
class Derived: private Base
{
  // Inherited private/protected
  // not public
};
 
// Driver code
int main()
{   
  Derived d1;
   
  // C-style cast allowed
  Base* b1 = (Base*)(&d1);
   
  // static_cast not allowed
  Base* b2 = static_cast<Base*>(&d1);
  return 0;
}


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

Еще одна мысль: сишные касты — это как топор. Ты им можешь что угодно отрубить, покромсать, оттяпать и так далее. А плюсовые касты — это набор разных специализированных инструментов, каждый под свою задачу. Используя касты ты даешь понять читателю, что ты хотел сделать этой конструкцией. Например, что вот тут ты просто убираешь const, а вот тут преобразуешь к наследуемому типу. Это делает код более читаемым и ясным -> снижает вероятность ошибки.

Ну и см. ссылки выше: самый главный аргумент все же тот самый type safety.
Патриот здравого смысла
Отредактировано 28.07.2023 15:13 DiPaolo . Предыдущая версия .
Re[3]: Сишный каст - зло?
От: B0FEE664  
Дата: 28.07.23 15:29
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>
M>>>auto u = (unsigned)(std::uint8_t)ch;
M>>>

M>Спасибо, кэп, я в курсе. Поэтому я сначала кастую к unsigned типу той же размерности, и только потом к unsigned int'у

Чтобы что? Чтобы напечать 'no' в следующем коде, если char — это signed?:
    const char ch = 254;
    const auto u = (unsigned)(std::uint8_t)ch;
    
    if ( ch == u )
        std::cout << "yes\n";
    else
        std::cout << "no\n";
И каждый день — без права на ошибку...
Отредактировано 28.07.2023 15:59 B0FEE664 . Предыдущая версия .
Re[12]: Сишный каст - зло?
От: B0FEE664  
Дата: 28.07.23 15:48
Оценка: +1
Здравствуйте, so5team, Вы писали:

S>Вот, из реального проекта (комментарии изъяты):

жуть.
И каждый день — без права на ошибку...
Re[13]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 16:10
Оценка:
Здравствуйте, B0FEE664, Вы писали:

S>>Вот, из реального проекта (комментарии изъяты):

BFE>жуть.

Нам очень важно ваше мнение, не сдерживайтесь. Оно имеет особую ценность в свете вот этого комментария: http://rsdn.org/forum/cpp/8570137.1
Автор: B0FEE664
Дата: 28.07.23
Отредактировано 28.07.2023 16:11 so5team . Предыдущая версия .
Re[3]: Сишный каст - зло?
От: Pzz Россия https://github.com/alexpevzner
Дата: 28.07.23 16:43
Оценка: :)
Здравствуйте, Marty, Вы писали:

M>Вот и я про что. Ну, grep static_cast, и что? Оно выдаст килотонны этих кастов, и накуя это нужно? А каст к конкретному типу можно и в случае сишного каста найти


Если миллионы, то следующая напрашивающаяся команда — rm -rf

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

Но в общем и целом, если ты мое личное мнение спросишь, я не вижу в сишном касте большого греха. Особенно если учесть, что мой рабочий язык — Си, не C++
Re[14]: Сишный каст - зло?
От: B0FEE664  
Дата: 28.07.23 17:02
Оценка:
Здравствуйте, so5team, Вы писали:

S>Нам очень важно ваше мнение, не сдерживайтесь.

Рад, что вы ждёте конструктивной критики.
Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем? Чтобы затруднить чтение кода?
А если image_bytes не указатель на const, то зачем тогда const у параметра ptr_cast?
Почему обращение к fresh_frame->data по индексу, а не по итератору?
Где assert(std::size(fresh_frame->data) == std::size(data_plane_sizes))?
Зачем столько вызовов ptr_cast? Не проще ли завести один указатель?
Уверены, что []( void *, std::uint8_t * ) -> void {} не ведёт к утечке памяти? (>24 байта за вызов)

S>Оно имеет особую ценность в свете вот этого комментария: http://rsdn.org/forum/cpp/8570137.1
Автор: B0FEE664
Дата: 28.07.23

Ну я же не знаю, что именно хочет автор, вот и спрашиваю.
И каждый день — без права на ошибку...
Re[15]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 28.07.23 20:05
Оценка:
Здравствуйте, B0FEE664, Вы писали:

S>>Нам очень важно ваше мнение, не сдерживайтесь.

BFE>Рад, что вы ждёте конструктивной критики.

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

BFE>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем?


Да, это const std::byte*, приходящий извне.

BFE>Почему обращение к fresh_frame->data по индексу, а не по итератору?


Потому что это Си-ный массив. Имитировать итераторы через вызовы std::begin/end не вижу смысла.

BFE>Где assert(std::size(fresh_frame->data) == std::size(data_plane_sizes))?


Во-первых, assert-ы -- это развлечение для тех, кто нуждается в песочнице под названием debug mode. В release они не работают, поэтому для меня они бесполезны.

Во-вторых, это гарантируется в принципе Upd: гарантируется, что (std::size(fresh_frame->data) >= std::size(data_plane_sizes)). By design, так сказать.

BFE>Зачем столько вызовов ptr_cast? Не проще ли завести один указатель?


Потому что исходный указатель, image_bytes, постоянно изменяется (это даже в приведенном кусочке видно). А по ходу дела его приходится приводить к std::uint8_t* (да, без const, такова специфика используемой внешней библиотеки). Можно было бы, конечно, вести сразу два указателя, image_bytes и второй, который имеет тип std::uint8_t. Но какой смысл дублировать одно и то же?

BFE>Уверены, что []( void *, std::uint8_t * ) -> void {} не ведёт к утечке памяти? (>24 байта за вызов)


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

Надеюсь, вы в курсе, что C++ная лямбда без захвата автоматически может приводится к указателю на функцию с таким же прототипом:
int main() {
    int (*pf)(char, long) = nullptr;
    auto dummy = [](char, long) -> int { return 42; };
    pf = dummy;
    return (*pf)('x', 100500);
}


S>>Оно имеет особую ценность в свете вот этого комментария: http://rsdn.org/forum/cpp/8570137.1
Автор: B0FEE664
Дата: 28.07.23

BFE>Ну я же не знаю, что именно хочет автор, вот и спрашиваю.

Т.е. вы никогда не наступали на грабли:
char x = -2;
auto u1 = static_cast<unsigned>(static_cast<unsigned char>(x));
auto u2 = static_cast<unsigned>(x);


?
Отредактировано 29.07.2023 4:47 so5team . Предыдущая версия .
Re[14]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 21:05
Оценка: :)
Здравствуйте, so5team, Вы писали:

S>>>Вот, из реального проекта (комментарии изъяты):

BFE>>жуть.

S>Нам очень важно ваше мнение, не сдерживайтесь. Оно имеет особую ценность в свете вот этого комментария: http://rsdn.org/forum/cpp/8570137.1
Автор: B0FEE664
Дата: 28.07.23


Вообще да, лично я согласен с B0FEE664, код максимально ужасен. Возможно, он всё формальные проверки и проходит, но он написан не для человека, который будет его поддерживать
Маньяк Робокряк колесит по городу
Re[4]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.07.23 21:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

M>>>>
M>>>>auto u = (unsigned)(std::uint8_t)ch;
M>>>>

M>>Спасибо, кэп, я в курсе. Поэтому я сначала кастую к unsigned типу той же размерности, и только потом к unsigned int'у

BFE>Чтобы что? Чтобы напечать 'no' в следующем коде, если char — это signed?:

BFE>
BFE>    const char ch = 254;
BFE>    const auto u = (unsigned)(std::uint8_t)ch;
    
BFE>    if ( ch == u )
BFE>        std::cout << "yes\n";
BFE>    else
BFE>        std::cout << "no\n";
BFE>



Откуда-то снаружи приходят данные в виде char'ов, какая-то упаковка протокола, например. По сути — данные беззнаковые, но библиотека выдаёт их в виде char. У меня же эти данные могут быть дополнены новыми значениями. Поэтому сначала привожу к беззнаковому типу того же размера, а потом расширяю размер. Если сразу размер расширить, могут быть сюрпризы
Маньяк Робокряк колесит по городу
Re[15]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 04:51
Оценка:
Здравствуйте, Marty, Вы писали:

M>Вообще да, лично я согласен с B0FEE664, код максимально ужасен. Возможно, он всё формальные проверки и проходит, но он написан не для человека, который будет его поддерживать


Убедительно, да (на самом деле нет).

Чтобы сделать разговор более предметным, три вопроса к вам:

1. У вас такой же список претензий/замечаний/вопросов/домыслов, как и у B0FEE664? Или же есть что добавить?

2. Если, по вашему мнению, код "максимально ужасен", то что могло бы его "исправить" (опять же по вашему мнению)?

3. Могли бы вы, для симметрии, привести фрагмент своего кода с кастами, дабы проиллюстрировать как должен выглядеть нормально написанный вами код?
Re[3]: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 29.07.23 06:45
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>Припоминаю аргументы:

M>>>1) Удобно искать cast'ы — но если на каждый чих их использовать, то любой поиск выдаст тонно-километры этих кастов. А если мы знаем точно, к какому типу ищем каст, то не всё ли равно, что искать — либо "_cast<TYPE>(", либо "(TYPE)"?
M>>>2) Сишный каст универсален, и беспринципно беспощаден — ну это есть, да, надо думать иногда, стоит ли использовать сишный каст или в узком месте использовать специализированный плюсовый каст. Может, просто стоит в код стайлах писать, в каких случаях надо использовать плюсовые касты, подразумевая, что в остальных случаях можно обойтись сишным кастом?

N>>Видишь, ты и сам всё знаешь.


M>Это довольно спорные аргументы


Я вижу в них безусловно ненулевую силу.

M>>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


M>>>ОбсудиПохоливарим?


N>>Ну если не обсуждать, что у C|C++ вообще надо менять не кран, а всю систему, то обсуждать и нечего


M>Ну, если тебе не нравится C++, может, тебе просто сменить язык, а не пытаться менять язык?


Меня одного не хватит.
The God is real, unless declared integer.
Re[5]: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 29.07.23 06:48
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>>>auto u = (unsigned)(std::uint8_t)ch;

M>>>Спасибо, кэп, я в курсе. Поэтому я сначала кастую к unsigned типу той же размерности, и только потом к unsigned int'у
M>Откуда-то снаружи приходят данные в виде char'ов, какая-то упаковка протокола, например. По сути — данные беззнаковые, но библиотека выдаёт их в виде char. У меня же эти данные могут быть дополнены новыми значениями. Поэтому сначала привожу к беззнаковому типу того же размера, а потом расширяю размер. Если сразу размер расширить, могут быть сюрпризы

255&ch работает универсально в рамках всех версий С|С++ c тем же успехом и прозрачнее (IMHO).

Хотя я бы подпёр юнит-тестом просто чтобы показать коллегам, что результат проверен.
The God is real, unless declared integer.
Re[16]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 09:51
Оценка: :)
Здравствуйте, so5team, Вы писали:

S>Чтобы сделать разговор более предметным, три вопроса к вам:


S>1. У вас такой же список претензий/замечаний/вопросов/домыслов, как и у B0FEE664? Или же есть что добавить?


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


S>2. Если, по вашему мнению, код "максимально ужасен", то что могло бы его "исправить" (опять же по вашему мнению)?



Для начала — нормально оформить


S>3. Могли бы вы, для симметрии, привести фрагмент своего кода с кастами, дабы проиллюстрировать как должен выглядеть нормально написанный вами код?


Да пожалуйста — https://rsdn.org/forum/flame.comp/8570205.1
Автор: Marty
Дата: 28.07.23


Правда, там кастов нет, лень искать.

ЗЫ, хотя, вот, лови:
  Скрытый текст
/*! \file
    \brief Тестируем вычисление длины строки в символах для UTF-8. Тестируем перемешивание букв внутри слова.
*/

#include "umba/umba.h"
//
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <iterator>
#include <random>
#include <cstdlib>
#include <exception>
#include <stdexcept>
#include <algorithm>
#include <random>

#include "../simple_encoding_api.h"
#include "../simple_file_api.h"

#include "marty_cpp/marty_cpp.h"
#include "marty_utf/utf.h"


int main( int argc, char* argv[] )
{
    UMBA_USED(argc);
    UMBA_USED(argv);

    //                 0        1         2         3
    //                 12345678901234567890123456789012
    std::string str = "Шла Маша по шошше и шошала шушку"; // 32 буквы

    std::cout << "str.size: " << str.size() << "\n";
    std::cout << "str.len : " << marty_utf::getStringLenUtf8(str) << "\n";


    std::string phrase = "На самом деле не важно, как располагаются буквы внутри слова, главное - чтобы перемешанные слова начинались и заканчивались на те же буквы, что и нормальные слова";

    std::vector<std::string> words = marty_cpp::simple_string_split(phrase, std::string(" "));

    std::random_device rd;
    std::mt19937 g(rd());

    for(auto &w: words)
    {
        auto w32 = marty_utf::utf32_from_utf8(w);

        if (w32.size()<4)
            continue;

        // std::random_shuffle(w32.begin()+1, w32.end()-1);

        if (w32.size()>10)
        {
            auto mid = w32.size()/2;
            std::shuffle(w32.begin()+ (std::ptrdiff_t)1u, w32.begin()+(std::ptrdiff_t)mid, g);
            std::shuffle(w32.begin()+(std::ptrdiff_t)mid, w32.end()  -(std::ptrdiff_t)2u , g);
        }
        else
        {
            std::shuffle(w32.begin()+(std::ptrdiff_t)1, w32.end()-(std::ptrdiff_t)2, g);
        }
        

        w = marty_utf::string_from_utf32(w32);
    }

    std::string shuffledPhase;
    for(const auto &w: words)
    {
        if (!shuffledPhase.empty())
        {
            shuffledPhase.append(1, ' ');
        }

        shuffledPhase.append(w);
    }

    std::cout << shuffledPhase << "\n";

    return 0;
}
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: alpha21264 СССР  
Дата: 29.07.23 10:24
Оценка: +1 :)
Здравствуйте, DiPaolo, Вы писали:


DP>Еще одна мысль: сишные касты — это как топор. Ты им можешь что угодно отрубить, покромсать, оттяпать и так далее. А плюсовые касты — это набор разных специализированных инструментов, каждый под свою задачу. Используя касты ты даешь понять читателю, что ты хотел сделать этой конструкцией. Например, что вот тут ты просто убираешь const, а вот тут преобразуешь к наследуемому типу. Это делает код более читаемым и ясным -> снижает вероятность ошибки.


Это делает код более захламлённым => менее читаемым и ясным.
Представь себе, что код ещё и какую-то логику делает, а не только типы преобразовывает.

Течёт вода Кубань-реки куда велят большевики.
Re[3]: Сишный каст - зло?
От: DiPaolo Россия  
Дата: 29.07.23 10:47
Оценка: +1
A>Это делает код более захламлённым => менее читаемым и ясным.
Не согласен. Как раз наоборот — я написал об этом — становится явно видна логика кода, что именно ты делаешь этим преобразованием.

A>Представь себе, что код ещё и какую-то логику делает, а не только типы преобразовывает.

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

О том, что нужно избегать кастов, написано в приведенной мною первой ссылке https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es48-avoid-casts.
Патриот здравого смысла
Re[17]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 13:36
Оценка: +1
Здравствуйте, Marty, Вы писали:

S>>1. У вас такой же список претензий/замечаний/вопросов/домыслов, как и у B0FEE664? Или же есть что добавить?


M>Я не вчитывался в смысл, потому что от одного оформления у меня кровь из глаз пошла


Экспертиза уровня Бох: что делается не знаю, как делается не вникал, увидел непривычное оформление и сразу вердикт "код ужасен".
Это, блин, какой-то детский сад, младшая ясельная группа.

S>>2. Если, по вашему мнению, код "максимально ужасен", то что могло бы его "исправить" (опять же по вашему мнению)?


M>Для начала — нормально оформить


Не постесняюсь спросить: а вы что, большую часть времени только с собственным кодом работаете? В чужой вообще не заглядываете?
Мне приходилось видеть и использовать разные стили оформления, так что на внешний вид, по большей части, пофиг, если только аффтары не злоупотребляют строками по 150+ символов длинной и функциями по 100+ строк.

S>>3. Могли бы вы, для симметрии, привести фрагмент своего кода с кастами, дабы проиллюстрировать как должен выглядеть нормально написанный вами код?


M>ЗЫ, хотя, вот, лови:

M>#include <iostream>
M>#include <iomanip>
M>#include <fstream>
...
M>#include <random>

Список инклюдов доставляет. Неприятный такой звоночек.

M>int main( int argc, char* argv[] )

M>{
M> UMBA_USED(argc);
M> UMBA_USED(argv);

Выглядит так, как будто вы 30 лет назад программировать учились. Я про UBMA_USED для аргументов функции, на которые забили.

M> if (w32.size()>10)

M> {
M> auto mid = w32.size()/2;
M> std::shuffle(w32.begin()+ (std::ptrdiff_t)1u, w32.begin()+(std::ptrdiff_t)mid, g);
M> std::shuffle(w32.begin()+(std::ptrdiff_t)mid, w32.end() -(std::ptrdiff_t)2u , g);
M> }
M> else
M> {
M> std::shuffle(w32.begin()+(std::ptrdiff_t)1, w32.end()-(std::ptrdiff_t)2, g);
M> }

Я, наверное, чего-то глобально не понимаю, но зачем это все?

Вот, по мотивам вашего кода минималистичный пример:
#include <algorithm>
#include <string>
#include <vector>
#include <random>

int main()
{
    std::mt19937 g{ std::random_device{}() };

    std::vector< std::string > words;

    for( auto & w : words )
    {
        auto w32 = w;
        if( w32.size() > 10u )
        {
            const auto mid = static_cast<std::ptrdiff_t>( w32.size() / 2 );
            std::shuffle( w32.begin() + 1, w32.begin() + mid, g );
            std::shuffle( w32.begin() + mid, w32.end() - 2, g );
        }
    }
}


Компилируем:
tmp\rsdn_cpp_20230729>cl -EHsc -WX -Wall -std:c++17 t1.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32532 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

t1.cpp
Microsoft (R) Incremental Linker Version 14.36.32532.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:t1.exe
t1.obj

Все. Никакого обилия кастов, не говоря уже про Си-шные касты.

Такое ощущение, что вы даже не дали себе труда подумать о том, что происходит. Вы явно используете литерал беззнакового типа, но вам-то нужен знаковый std::ptrdiff_t, поэтому вы недолго думая херачите Си-шный каст и получаете угребищный (std::ptrdiff_t)1u там, где достаточно всего лишь обычной единички.
Отредактировано 29.07.2023 13:37 so5team . Предыдущая версия .
Re[18]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 13:49
Оценка:
Здравствуйте, so5team, Вы писали:


S>Не постесняюсь спросить: а вы что, большую часть времени только с собственным кодом работаете? В чужой вообще не заглядываете?

S>Мне приходилось видеть и использовать разные стили оформления, так что на внешний вид, по большей части, пофиг, если только аффтары не злоупотребляют строками по 150+ символов длинной и функциями по 100+ строк.

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


S>>>3. Могли бы вы, для симметрии, привести фрагмент своего кода с кастами, дабы проиллюстрировать как должен выглядеть нормально написанный вами код?


M>>ЗЫ, хотя, вот, лови:

M>>#include <iostream>
M>>#include <iomanip>
M>>#include <fstream>
S>...
M>>#include <random>

S>Список инклюдов доставляет. Неприятный такой звоночек.


Это один из тестов, просто генерится из шаблона


M>>int main( int argc, char* argv[] )

M>>{
M>> UMBA_USED(argc);
M>> UMBA_USED(argv);

S>Выглядит так, как будто вы 30 лет назад программировать учились. Я про UBMA_USED для аргументов функции, на которые забили.


Есть варианты лучше?


M>> if (w32.size()>10)

M>> {
M>> auto mid = w32.size()/2;
M>> std::shuffle(w32.begin()+ (std::ptrdiff_t)1u, w32.begin()+(std::ptrdiff_t)mid, g);
M>> std::shuffle(w32.begin()+(std::ptrdiff_t)mid, w32.end() -(std::ptrdiff_t)2u , g);
M>> }
M>> else
M>> {
M>> std::shuffle(w32.begin()+(std::ptrdiff_t)1, w32.end()-(std::ptrdiff_t)2, g);
M>> }

S>Я, наверное, чего-то глобально не понимаю, но зачем это все?


Что именно?


S>Такое ощущение, что вы даже не дали себе труда подумать о том, что происходит. Вы явно используете литерал беззнакового типа, но вам-то нужен знаковый std::ptrdiff_t, поэтому вы недолго думая херачите Си-шный каст и получаете угребищный (std::ptrdiff_t)1u там, где достаточно всего лишь обычной единички.



Да, не трудился. На автомате
Маньяк Робокряк колесит по городу
Re[4]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 13:53
Оценка:
Здравствуйте, DiPaolo, Вы писали:

A>>Это делает код более захламлённым => менее читаемым и ясным.

DP>Не согласен. Как раз наоборот — я написал об этом — становится явно видна логика кода, что именно ты делаешь этим преобразованием.

A>>Представь себе, что код ещё и какую-то логику делает, а не только типы преобразовывает.

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

99% кастов — это снятие/добавление знака, расширение/сужение типа. Там плюсовые касты нахрен не упёрлись. В тех случаях, когда что-то другое надо — тогда да, плюсовые касты вполне уместны
Маньяк Робокряк колесит по городу
Re[19]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 13:57
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>int main( int argc, char* argv[] )

M>>>{
M>>> UMBA_USED(argc);
M>>> UMBA_USED(argv);

S>>Выглядит так, как будто вы 30 лет назад программировать учились. Я про UBMA_USED для аргументов функции, на которые забили.


M>Есть варианты лучше?


Да. Например:
void f(int /*some_arg*/) {
}

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

Если же в прологе функции делать так:
int main(int argc, char ** argv) {
  (void)argc; // Старая школа.
  std::ignore = argv; // Можно и молодежно.
}

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

M>Да, не трудился. На автомате


О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.
Re[5]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 13:59
Оценка:
Здравствуйте, Marty, Вы писали:

M>99% кастов — это снятие/добавление знака, расширение/сужение типа.


Отучаемся говорить за всех (c)

M>Там плюсовые касты нахрен не упёрлись.


Старого пса, походу, новым трюкам не обучишь
Re[20]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 14:30
Оценка: :)
Здравствуйте, so5team, Вы писали:


M>>Есть варианты лучше?


S>Да. Например:

S>
S>void f(int /*some_arg*/) {
S>}
S>

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

В прототипе одно, в реализации — другое?
А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0


S>Если же в прологе функции делать так:

S>
S>int main(int argc, char ** argv) {
S>  (void)argc; // Старая школа.
S>  std::ignore = argv; // Можно и молодежно.
S>}
S>

S>то вы теряете вменяемые предупреждения от компилятора, если забыли использовать параметр в коде.

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


M>>Да, не трудился. На автомате


S>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.


Или нет
Маньяк Робокряк колесит по городу
Re[21]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 14:39
Оценка:
Здравствуйте, Marty, Вы писали:

M>В прототипе одно, в реализации — другое?


Если вы про это:
// .hpp-файл.

void f(int some_arg);

// .cpp-файл.
void f(int /*some_arg*/) {
  ...
}

То я не понимаю в чем проблема. Компилятор интересует только реализация, какие имена аргументов в декларации ему фиолетово.

M>А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0


Не устраивают комментарии вокруг имени, вообще уберите имя:
void f(int) {
  ...
}


M>Я ничего не теряю, потому что USED добавляю, когда всё уже реализовано


Ох, ё.

M>Или нет


Ох, ё-ё-ё.

А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.
Re[22]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 14:58
Оценка:
Здравствуйте, so5team, Вы писали:

S>То я не понимаю в чем проблема. Компилятор интересует только реализация, какие имена аргументов в декларации ему фиолетово.


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


M>>А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0


S>Не устраивают комментарии вокруг имени, вообще уберите имя:

S>
S>void f(int) {
S>  ...
S>}


Приходим к тому, что у декларации и реализации записано по разному. Ну, или можно из декларации тоже всё убрать, отличная идея.



S>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.


Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД
Маньяк Робокряк колесит по городу
Re[23]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 15:04
Оценка: +1
Здравствуйте, Marty, Вы писали:

S>>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.


M>Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД


С моей колокольни это видно так: научить можно лишь того, что хочет научится.
Re: Сишный каст - зло?
От: andrey.desman  
Дата: 29.07.23 15:07
Оценка: +2
Здравствуйте, Marty, Вы писали:

M>В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.


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


M>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


Зачем искать касты?
Re[24]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 15:12
Оценка:
Здравствуйте, so5team, Вы писали:

S>>>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.


M>>Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД


S>С моей колокольни это видно так: научить можно лишь того, что хочет научится.


А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 15:14
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.


AD>Для указателей использую плюсовые касты, для арифметики конструкторы.

AD>Сишные касты для указателнй слишком жестоки, а для арифметических типов многовато скобок получается — он вам не Лисп!

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


M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


AD>Зачем искать касты?


Ну, я не знаю, любители плюсовых кастов говорят, что их искать проще
Маньяк Робокряк колесит по городу
Re[25]: Сишный каст - зло?
От: DiPaolo Россия  
Дата: 29.07.23 15:15
Оценка: +1
M>А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься

Да нет же: сишный каст — это НЕ абсолютное зло. И имеет право на существование. Но так как в плюсах итак дохрена мест, в которых можно отстрелить себе ноги, лучше сводить риски к минимуму. Опять же: это всего лишь рекомендации, дальше уж каждый делает как считает нужным.
Патриот здравого смысла
Re[25]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 15:32
Оценка:
Здравствуйте, Marty, Вы писали:

M>А я не просил меня учить


Усвоение новой информации это уже не учеба? Ну ОК, как уже было сказано, любитесь как хотите.

M>Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься


Если вы не заметили, я здесь один из двух человек (второй DiPaolo), который хоть что-то приводит в подтверждение своих слов и единственный, который делает это на конкретных примерах. Если это "предоставлять не хочет", то... Любитесь как хотите, опять же.

И кстати, на счет "предоставлять не хочешь": http://rsdn.org/forum/cpp/8570520.1
Автор: Marty
Дата: 29.07.23

Хотелось бы увидеть ответ на простой вопрос.
Re[2]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 15:35
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


AD>Зачем искать касты?


Ну как же. Вот будет в интернете кто-то неправ не поверит тов.Marty, что приходится снимать константность с указателя. А ты такой "Хоп!" и простым grep-ом по исходникам обнаруживаешь места, где const_cast используется. Ну красота же!
Re: Сишный каст - зло?
От: CRT  
Дата: 29.07.23 19:14
Оценка:
Здравствуйте, Marty, Вы писали:

M>Или битовые операторы и операторы сдвига — они, как оказалось, возвращают int/int64, а не тот тип, который изначально участвует в выражении. Полечил сишными кастами.


Про целочисленное расширение (integral promotion) почитай
Re[6]: Сишный каст - зло?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 30.07.23 01:07
Оценка:
Здравствуйте, so5team, Вы писали:

S>У меня нет под рукой собственной ошибки (хотя компилятор несколько раз в год бьет по рукам в попытках неправильно использовать static_cast, особенно в обобщенном коде). Но вот хороший пример из Интернета:

Добавь reinterpret_cast
Sic luceat lux!
Re: Сишный каст - зло?
От: rg45 СССР  
Дата: 30.07.23 07:01
Оценка: 2 (1) +3
Здравствуйте, Marty, Вы писали:

M>Почему сишным кастом пользоваться плохо?


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

M>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:

M>
M>auto u = (unsigned)(std::uint8_t)ch;
M>


M>Но можно и так:

M>
M>auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
M>


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


Я могу преложить тебе компромиссный вариант — functional-style cast expression, почитать можно здесь: https://en.cppreference.com/w/cpp/language/explicit_cast

auto u = unsigned(std::uint8_t(ch));


Для простых типов такое преобразование эквивалентно C-style cast, но, на мой взгляд, обладает несколькими преимуществами:
1) его невозможно ПО ОШИБКЕ применить к ссылке, указателю или какому-то еще типу, состоящему из двух и более лексем
2) для объектов классов такая запись будет означать инициализацию через конструктор
3) как по мне, у этой записи более приятный вид как по сравнению с C-cast, так и по сравнению с C++-cast записями

Впрочем, все сказанное — это мое имхо, на истину в последней инстанции не претендую.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[25]: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 30.07.23 07:58
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься


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

Сишные касты 1) заменяются на плюсовые без проблем, и в ~90% случаев каждый — одним кастом. 2) Грепабельны. Этого достаточно, чтобы форсировать их применение для большинства случаев.

Ну и, естественно, нужен какой-то механизм оставлять сишные с явной пометкой "Here be dragons", как же без этого. Но полиси типа "допускать такое только когда убедишь коллегу-ревьюера" вполне эффективно.
The God is real, unless declared integer.
Re[20]: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 30.07.23 08:02
Оценка: +1
Здравствуйте, so5team, Вы писали:

S>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.


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

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

char *strchr(const char *s, int c);


тут надо или человеку следить за присвоением результата указателю на const, или анализатор учить специфике именно таких функций...
The God is real, unless declared integer.
Re[21]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 30.07.23 09:02
Оценка: +1
Здравствуйте, netch80, Вы писали:

S>>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.


N>Только в куче случаев это недодумка самого языка. Начиная с обсуждённых тут плясок вокруг размерности и знаковости типов.


Я так понимаю, что аргумент защитников Си-шных кастов состоит в том, что когда приходится делать касты (как из-за недодумок языка, так и по другим причинам), то Си-шный каст может быть предпочтительным из-за того, что писать нужно меньше, чем при использовании static_cast/const_cast/reinterpret_cast. И вот с этим я не согласен в том плане, что язык уже предоставляет инструменты для уменьшения синтаксического оверхэда. И если даже касты мы вынуждены применять из-за недодумок языка, то у нас есть возможности написать код так, чтобы совсем уж ужасно он не выглядел.
Re: Сишный каст - зло?
От: _NN_ www.nemerleweb.com
Дата: 30.07.23 10:45
Оценка: +1
Здравствуйте, Marty, Вы писали:

У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов.
Например pointer_cast
Автор: _nn_
Дата: 28.04.06
.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.07.23 10:56
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов.

_NN>Например pointer_cast
Автор: _nn_
Дата: 28.04.06
.


Это чем же C-style или constructor style касты неоднородны в синтаксисе с пользовательскими приведениями типов?
Маньяк Робокряк колесит по городу
Re[3]: Сишный каст - зло?
От: _NN_ www.nemerleweb.com
Дата: 30.07.23 14:23
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, _NN_, Вы писали:


_NN>>У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов.

_NN>>Например pointer_cast
Автор: _nn_
Дата: 28.04.06
.


M>Это чем же C-style или constructor style касты неоднородны в синтаксисе с пользовательскими приведениями типов?


Тем, что нельзя «перегрузить» для примитивных типов.
К примеру lexical_cast<int> , pointer_cast<int*> .
Как это сделать в стиле конструктора ?

Можно конечно через промежуточный объект и операцию преобразования:
PointerCast<int*>(ptr) с каким-нибудь operator int*().
Но тут у нас лишние сущности получаются.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[16]: Сишный каст - зло?
От: B0FEE664  
Дата: 31.07.23 10:36
Оценка: :)
Здравствуйте, so5team, Вы писали:

BFE>>Рад, что вы ждёте конструктивной критики.

S>Для конструктивной нужно, чтобы критик понимал предмет разговора. Так что нет, не жду.
Т.е. вы думаете, что ваш код никто не поймёт?

BFE>>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем?

S>Да, это const std::byte*, приходящий извне.
Но зачем нарушать контракт про "const"?

BFE>>Почему обращение к fresh_frame->data по индексу, а не по итератору?

S>Потому что это Си-ный массив. Имитировать итераторы через вызовы std::begin/end не вижу смысла.
Почему "эмитировать"? То, что в данном случае итератор — это указатель, ничего не меняет.

BFE>>Где assert(std::size(fresh_frame->data) == std::size(data_plane_sizes))?

S>Во-первых, assert-ы -- это развлечение для тех, кто нуждается в песочнице под названием debug mode. В release они не работают, поэтому для меня они бесполезны.
Это дело вкуса. То, что assert-ы не работают в release — опасное заблуждение.

S>Во-вторых, это гарантируется в принципе Upd: гарантируется, что (std::size(fresh_frame->data) >= std::size(data_plane_sizes)). By design, так сказать.

Если By design, то где static_assert?

BFE>>Зачем столько вызовов ptr_cast? Не проще ли завести один указатель?

S>Потому что исходный указатель, image_bytes, постоянно изменяется (это даже в приведенном кусочке видно). А по ходу дела его приходится приводить к std::uint8_t* (да, без const, такова специфика используемой внешней библиотеки). Можно было бы, конечно, вести сразу два указателя, image_bytes и второй, который имеет тип std::uint8_t. Но какой смысл дублировать одно и то же?
Чтобы не полагаться на оптимизатор.

BFE>>Уверены, что []( void *, std::uint8_t * ) -> void {} не ведёт к утечке памяти? (>24 байта за вызов)

S>Мне сложно представить откуда здесь может взяться утечка, т.к. этот фрагмент -- это получение указателя на функцию, которая ничего не делает. Данный указатель требуется для av_buffer_create в качестве "деаллокатора".
А то я не вижу!

S>Но т.к. деаллокатор здесь не нужен, то и функция пуста.

Вот и хотелось бы понять почему деаллокатор не нужен.
Вот в этой строчке заказ памяти AVBuffer *buf = av_mallocz(sizeof(*buf));:
 AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
                               void (*free)(void *opaque, uint8_t *data),
                               void *opaque, int flags)
 {
     AVBufferRef *ret;
     AVBuffer *buf = av_mallocz(sizeof(*buf)); // тут заказали память под AVBuffer 
     if (!buf)
         return NULL;
  
     ret = buffer_create(buf, data, size, free, opaque, flags);
     if (!ret) {
         av_free(buf);
         return NULL;
     }
     return ret;
 }


смотрим дальше:
 static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
                                   void (*free)(void *opaque, uint8_t *data),
                                   void *opaque, int flags)
 {
     AVBufferRef *ref = NULL;
  
     buf->data     = data;
     buf->size     = size;
     buf->free     = free ? free : av_buffer_default_free; // т.к. free не NULL, то она будет использована вместо av_buffer_default_free
     buf->opaque   = opaque;
  
     atomic_init(&buf->refcount, 1);// очевидно подсчёт числа "ссылок", т.о. ниже идёт имитация intrusive смарт указателя
  
     buf->flags = flags;
  
     ref = av_mallocz(sizeof(*ref)); // заказали память под "ссылку"
     if (!ref)
         return NULL;
  
     ref->buffer = buf;  // в "ссылку" положили указатель на объект AVBuffer. это, впрочем, не важно.
     ref->data   = data;
     ref->size   = size;
  
     return ref;
 }

Таким образом в av_mallocz заказывается память под объект типа AVBufferRef, но вот освобождения этой памяти нет. Следовательно: либо это утечка памяти, либо вы как-то подменили av_mallocz, но если посмотреть:
 void *av_mallocz(size_t size)
 {
     void *ptr = av_malloc(size);
     if (ptr)
         memset(ptr, 0, size);
     return ptr;
 }

и
  av_malloc
void *av_malloc(size_t size)
 {
     void *ptr = NULL;
  
     if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))
         return NULL;
  
 #if HAVE_POSIX_MEMALIGN
     if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
     if (posix_memalign(&ptr, ALIGN, size))
         ptr = NULL;
 #elif HAVE_ALIGNED_MALLOC
     ptr = _aligned_malloc(size, ALIGN);
 #elif HAVE_MEMALIGN
 #ifndef __DJGPP__
     ptr = memalign(ALIGN, size);
 #else
     ptr = memalign(size, ALIGN);
 #endif
     /* Why 64?
      * Indeed, we should align it:
      *   on  4 for 386
      *   on 16 for 486
      *   on 32 for 586, PPro - K6-III
      *   on 64 for K7 (maybe for P3 too).
      * Because L1 and L2 caches are aligned on those values.
      * But I don't want to code such logic here!
      */
     /* Why 32?
      * For AVX ASM. SSE / NEON needs only 16.
      * Why not larger? Because I did not see a difference in benchmarks ...
      */
     /* benchmarks with P3
      * memalign(64) + 1          3071, 3051, 3032
      * memalign(64) + 2          3051, 3032, 3041
      * memalign(64) + 4          2911, 2896, 2915
      * memalign(64) + 8          2545, 2554, 2550
      * memalign(64) + 16         2543, 2572, 2563
      * memalign(64) + 32         2546, 2545, 2571
      * memalign(64) + 64         2570, 2533, 2558
      *
      * BTW, malloc seems to do 8-byte alignment by default here.
      */
 #else
     ptr = malloc(size);
 #endif
     if(!ptr && !size) {
         size = 1;
         ptr= av_malloc(1);
     }
 #if CONFIG_MEMORY_POISONING
     if (ptr)
         memset(ptr, FF_MEMORY_POISON, size);
 #endif
     return ptr;
 }

то я не вижу как, можно было бы подменить заказ памяти.
Таким образом: вы всё ещё уверены, что здесь нет утечки памяти?
И каждый день — без права на ошибку...
Re[17]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 31.07.23 11:23
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Рад, что вы ждёте конструктивной критики.

S>>Для конструктивной нужно, чтобы критик понимал предмет разговора. Так что нет, не жду.
BFE>Т.е. вы думаете, что ваш код никто не поймёт?

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

BFE>>>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем?

S>>Да, это const std::byte*, приходящий извне.
BFE>Но зачем нарушать контракт про "const"?

Потому, что в FFMPEG нужно иметь неконстантный указатель.

BFE>>>Почему обращение к fresh_frame->data по индексу, а не по итератору?

S>>Потому что это Си-ный массив. Имитировать итераторы через вызовы std::begin/end не вижу смысла.
BFE>Почему "эмитировать"? То, что в данном случае итератор — это указатель, ничего не меняет.

Потому, что мне здесь "итераторы" в каком-либо виде не нужны. Если вам кажется, что нужны, то, наверное, для этого есть какие-то доводы?

BFE>Это дело вкуса.


Скорее опыта.

BFE>То, что assert-ы не работают в release — опасное заблуждение.


Если assert-ы работают в релизе, то это уже не assert-ы.

S>>Во-вторых, это гарантируется в принципе Upd: гарантируется, что (std::size(fresh_frame->data) >= std::size(data_plane_sizes)). By design, так сказать.

BFE>Если By design, то где static_assert?

В Караганде, вероятно. Потому что by design. Т.к. если в FFMPEG внезапно сделают так, что в AVFrame::data будет меньше элементов, чем в аргументе linesizes для av_image_fill_plane_sizes, то нужно будет что-то менять в консерватории. Может быть законченный параноик будет напишет (не один) static_assert чтобы защититься от такой гипотетической ситуации, но я подобной паранойей еще не страдаю.

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

BFE>>>Зачем столько вызовов ptr_cast? Не проще ли завести один указатель?

S>>Потому что исходный указатель, image_bytes, постоянно изменяется (это даже в приведенном кусочке видно). А по ходу дела его приходится приводить к std::uint8_t* (да, без const, такова специфика используемой внешней библиотеки). Можно было бы, конечно, вести сразу два указателя, image_bytes и второй, который имеет тип std::uint8_t. Но какой смысл дублировать одно и то же?
BFE>Чтобы не полагаться на оптимизатор.

Оптимизатор-то здесь причем? Или вы думаете, что на reinterpret_cast+const_cast есть какие-то накладные расходы в run-time?

BFE>>>Уверены, что []( void *, std::uint8_t * ) -> void {} не ведёт к утечке памяти? (>24 байта за вызов)

S>>Мне сложно представить откуда здесь может взяться утечка, т.к. этот фрагмент -- это получение указателя на функцию, которая ничего не делает. Данный указатель требуется для av_buffer_create в качестве "деаллокатора".
BFE>А то я не вижу!

Раз высказываете такие опасения, значит не видите. Или видите что-то свое.

S>>Но т.к. деаллокатор здесь не нужен, то и функция пуста.

BFE>Вот и хотелось бы понять почему деаллокатор не нужен.

Потому что это деаллокатор не для AVBuffer, а для AVBuffer::data.
Вызывается этот деаллокатор здесь (через здесь):
static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
 {
     AVBuffer *b;
  
     b = (*dst)->buffer;
  
     if (src) {
         **dst = **src;
         av_freep(src);
     } else
         av_freep(dst);
  
     if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
         /* b->free below might already free the structure containing *b,
          * so we have to read the flag now to avoid use-after-free. */
         int free_avbuffer = !(b->flags_internal & BUFFER_FLAG_NO_FREE);
         b->free(b->opaque, b->data);
         if (free_avbuffer)
             av_free(b);
     }
 }


BFE>Таким образом: вы всё ещё уверены, что здесь нет утечки памяти?


Я ни в чем на 100% не уверен, но в данном случае очень надеюсь.
Отредактировано 31.07.2023 11:27 so5team . Предыдущая версия .
Re[18]: Сишный каст - зло?
От: B0FEE664  
Дата: 31.07.23 12:54
Оценка:
Здравствуйте, so5team, Вы писали:

S>Я очень надеюсь, что критиковать код начнут после того как поймут, а не до.

Ну уж нет. Код должен читаться, а не являться ребусом.

BFE>>>>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем?

S>>>Да, это const std::byte*, приходящий извне.
Да, это я не правильный вопрос задал. Попытаюсь ещё раз. Почему извне приходить указатель на константные данные?

S>Потому, что мне здесь "итераторы" в каком-либо виде не нужны. Если вам кажется, что нужны, то, наверное, для этого есть какие-то доводы?

Вот этот цикл:
std::size_t plane_index = 0u;
for( const auto plane_size : data_plane_sizes )
{
    fresh_frame->data[ plane_index ] = ptr_cast( image_bytes );
    image_bytes += plane_size;
    ++plane_index;
}

я бы переписал так:
auto pImgBytes = ptr_cast( image_bytes );
auto pData     = std::begin(fresh_frame->data);
for( const auto plane_size : data_plane_sizes )
{
    *pData++   = pImgBytes;
    pImgBytes += plane_size;
}


BFE>>То, что assert-ы не работают в release — опасное заблуждение.

S>Если assert-ы работают в релизе, то это уже не assert-ы.
А что тогда?

S>В Караганде, вероятно. Потому что by design. Т.к. если в FFMPEG внезапно сделают так, что в AVFrame::data будет меньше элементов, чем в аргументе linesizes для av_image_fill_plane_sizes, то нужно будет что-то менять в консерватории. Может быть законченный параноик будет напишет (не один) static_assert чтобы защититься от такой гипотетической ситуации, но я подобной паранойей еще не страдаю.

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

S>Потому что это деаллокатор не для AVBuffer, а для AVBuffer::data.

Ага. теперь понятно.
И каждый день — без права на ошибку...
Re[19]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 31.07.23 13:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

S>>Я очень надеюсь, что критиковать код начнут после того как поймут, а не до.

BFE>Ну уж нет. Код должен читаться, а не являться ребусом.

Код должен решать задачу. При этом (но не вместо!) он должен быть понятным, корректным, надежным, сопровождабельным и т.д.
Но код пишется для решения задачи. И так бывает, что для решения задачи нужно понимание особенностей предметной области (хотя бы на уровне знакомства с используемым инструментарием), без которого (без понимания в смысле) читабельность кода -- это очень эфемерное, но спекулятивное понятие.

BFE>>>>>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем?

S>>>>Да, это const std::byte*, приходящий извне.
BFE>Да, это я не правильный вопрос задал. Попытаюсь ещё раз. Почему извне приходить указатель на константные данные?

Объективная реальность. Скажем, какие-то данные берутся из shared-memory, замапленной в память процесса в режиме read-only.

S>>Потому, что мне здесь "итераторы" в каком-либо виде не нужны. Если вам кажется, что нужны, то, наверное, для этого есть какие-то доводы?

BFE>Вот этот цикл:
BFE>
BFE>std::size_t plane_index = 0u;
BFE>for( const auto plane_size : data_plane_sizes )
BFE>{
BFE>    fresh_frame->data[ plane_index ] = ptr_cast( image_bytes );
BFE>    image_bytes += plane_size;
BFE>    ++plane_index;
BFE>}
BFE>

BFE>я бы переписал так:
BFE>
BFE>auto pImgBytes = ptr_cast( image_bytes );
BFE>auto pData     = std::begin(fresh_frame->data);
BFE>for( const auto plane_size : data_plane_sizes )
BFE>{
BFE>    *pData++   = pImgBytes;
BFE>    pImgBytes += plane_size;
BFE>}
BFE>


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

BFE>>>То, что assert-ы не работают в release — опасное заблуждение.

S>>Если assert-ы работают в релизе, то это уже не assert-ы.
BFE>А что тогда?

Обычные run-time проверки но с самым, пожалуй, жестким способом реакции на проблему.

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


См. выше про потребность быть в предметной области.
Re[20]: Сишный каст - зло?
От: B0FEE664  
Дата: 31.07.23 13:27
Оценка:
Здравствуйте, so5team, Вы писали:

S>Объективная реальность. Скажем, какие-то данные берутся из shared-memory, замапленной в память процесса в режиме read-only.


Не, ну так не честно! Я думал речь про нормальную программу, а не про хакерство.
И всё равно не понятно, зачем вызывать cast на каждый доступ.
И каждый день — без права на ошибку...
Re[21]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 31.07.23 14:23
Оценка:
Здравствуйте, B0FEE664, Вы писали:

S>>Объективная реальность. Скажем, какие-то данные берутся из shared-memory, замапленной в память процесса в режиме read-only.


BFE>Не, ну так не честно! Я думал речь про нормальную программу, а не про хакерство.


Хакерство здесь не при чем. Можно смотреть на вещи так: есть подсистема A, у которой откуда-то в памяти появляются данные. Часть этих данных должна попасть к подсистеме B, но только на чтение, поэтому подсистема A отдает подсистеме B const-указатель. Далее подсистеме B нужно сформировать AVFrame, который бы использовал данные по полученному указателю. Но тут засада, в AVBuffer указатель неконстантный. Отсюда и происхождение const_cast.

При этом параллельно с подсистемой B над теми же самыми данными может работать и какая-нибудь подсистема C или D. И они так же не должны ничего по указателю менять, поэтому и к ним так же пойдет const-указатель.

BFE>И всё равно не понятно, зачем вызывать cast на каждый доступ.


Там же не зря image_bytes постоянно инкрементируется, т.к. его результирующее значение важно и используется впоследствии (за пределами процитированного фрагмента).
Посему выбор просто:

1) либо работать с исходным константным image_bytes, применяя cast только в тех местах, где реально нужен неконстантный указатель;
2) либо создать временный неконстантный указатель из image_bytes, работать с ним, а потом его значение возвращать, но уже в виде константного.

Второй вариант мне нравится сильно меньше, т.к. значительно увеличивается область, в которой живет неконстантный указатель на константные, по сути, данные.
Re[22]: Сишный каст - зло?
От: B0FEE664  
Дата: 31.07.23 16:44
Оценка:
Здравствуйте, so5team, Вы писали:

S>Но тут засада, в AVBuffer указатель неконстантный.

Вот я тормоз!
Я правильно понимаю, что данные на самом деле не меняются, а просто в библиотеке не отличают константный буфер от неконстантного?
И каждый день — без права на ошибку...
Re[23]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 31.07.23 17:01
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

S>>Но тут засада, в AVBuffer указатель неконстантный.

BFE>Вот я тормоз!
BFE>Я правильно понимаю, что данные на самом деле не меняются, а просто в библиотеке не отличают константный буфер от неконстантного?

Именно так.
Re[11]: Сишный каст - зло?
От: student__  
Дата: 03.08.23 14:39
Оценка:
Здравствуйте, Marty, Вы писали:

M>Собери свой проект с /Wall /WX, удивись, сколько варнингов [...]


(Внезапно!) все, кто серьезно относятся к качеству кода с дня нумер один разработки (а не постфактум, да ради прикола), уже собирают со всеми флагами "хорошего тона", и никаких удивлений у них нет.
Иногда еще даже с -Werror впридачу.
Re: Сишный каст - зло?
От: Кодт Россия  
Дата: 07.08.23 11:44
Оценка: 21 (2) +2
Здравствуйте, Marty, Вы писали:

M>Почему сишным кастом пользоваться плохо?


Потому что он умеет втихаря снимать константность и реинтерпретировать. Это позволяет на ровном месте устроить ад и израиль.
Тогда как плюсовые касты явно выражают намерение.

M>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:

M>
M>auto u = (unsigned)(std::uint8_t)ch;
M>


M>Но можно и так:

M>
M>auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
M>


Но можно и так
constexpr unsigned unsigned_from_char(char c) { return static_cast<unsigned>(static_cast<unsigned char>(c)); }
constexpr unsigned unsigned_from_char(auto) = delete;  // во избежание неявных кастов

...
auto u = unsigned_from_char(ch);
...


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


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

M>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


M>ОбсудиПохоливарим?


Придёт ПМ, включит линтер и-или
-Werror=old-style-cast
(или как оно там в комстроке...) — и холиварь с начальством сколько влезет
Перекуём баги на фичи!
Re[11]: Сишный каст - зло?
От: Кодт Россия  
Дата: 07.08.23 11:55
Оценка:
Здравствуйте, Marty, Вы писали:

M>Собери свой проект с /Wall /WX, удивись, сколько варнингов будет в простейших битовых выражениях, расставь там плюсовые касты и попробуй это прочитать


Я последние несколько гигантских проектов собирал (в том числе форк хромиума и форк Robotic OS) исключительно с параноидными настройками компилятора.
И ничего.
Сложно первые полгода, пока всё говнище от старых дореформенных разработчиков не вычистишь. Естетственно, не в одно лицо, там трудозатрат на десятки человеко-лет.
А потом — просто не говнокодишь; а линтер и тесты, (а в некоторых случаях — живые ревьюверы) тебе помогают-заставляют.
Перекуём баги на фичи!
Re[5]: Сишный каст - зло?
От: Skorodum Россия  
Дата: 23.08.23 14:36
Оценка:
Здравствуйте, Marty, Вы писали:

M>И это всё как-то работает

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