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 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.