Вы не можете спрашивать о приведении в 'C' без понимания того, что приведение охватывает более одного типа операций. Существуют два, преобразование типов и приведение типов. В C ++, поскольку он имеет больше информации о типах, он создает 4 типа приведений и кодифицирует это с эксклюзивной нотацией. reinterpret_cast<>
, const_cast<>
, dynamic_cast<>
и static_cast<>
. У вас их нет в C, поскольку у всех приведений есть синтаксис (ctype)
, но причины для них остаются, и это помогает понять, почему приведение требуется, даже если ваш вопрос касался именно C.
«Потребность» в статическом приведении - это то, что вы показываете в своем примере. Компилятор сделает их за вас, даже если вы не укажете его - однако, уровень предупреждения поднимется достаточно высоко, и компилятор предупредит вас, если произойдет потеря точности при переходе от двойного к плавающему (ваш return bar;
заявление). Добавление приведения говорит компилятору, что потеря точности была запланирована.
Вторым наименее опасным составом является постоянный состав <>. Используется для удаления const или volatile из типа. Это обычно происходит, когда структуры имеют внутренние «кэши». Таким образом, вызывающая сторона может иметь константную версию вашей структуры, но «внутренней функции» необходимо обновить кэш, поэтому ей придется преобразовывать указатель на константную структуру в обычную структуру для обновления внутреннего поля.
Самым опасным типом является переосмысление актеров и то, почему люди будут продолжать и дальше рассказывать о том, как это плохо. Здесь вы ничего не конвертируете, а говорите компилятору переосмыслить значение как совершенно другой тип. То, что ниже, возможно, было добавлено наивным программистом, пытающимся избавиться от ошибки компилятора.
char **ptostr = (char **p) "this is not a good idea";
Вероятно, правильным решением было использование '&', и именно так кастинг получает плохую репутацию. Такие приведения могут быть использованы для добра или зла. Я использовал его в ответе на другой вопрос о том, как найти наименьшую мощность 2 , чтобы использовать мощность FPU в процессоре. Лучший пример хорошего использования - это реализация связанных списков. Если ссылки находятся в самих объектах, вы должны привести от указателя ссылки обратно к вложенному объекту (хороший вариант для макроса offsetof, если ссылки не могут быть в верхней части структуры).
Динамическое приведение не имеет языковой поддержки в C, но обстоятельство все еще возникает. Если у вас есть гетерогенный список, вы можете проверить, что объект был заданного типа, используя поле в заголовке ссылки списка. Реализованный вручную, вы проверите тип как совместимый и вернете NULL, если это не так. Это специальная версия реинтерпретации.
Существует много сложных шаблонов программирования, которые требуют приведения, поэтому я бы не сказал, что приведения необходимо избегать, или указывает, что что-то не так. Проблема с 'C' заключается в том, что вы пишете небезопасные точно так же, как и безопасные. Хорошая практика заключается в том, чтобы хранить ее в ограниченном количестве, поэтому вы можете убедиться, что она у вас правильная (например, использовать библиотечные процедуры, строгую типизацию и утверждать, если можете).