Всегда ли явное приведение совпадает с неявным преобразованием?
В Visual C I есть:
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
typedef int HFILE;
HFILE stat_fh = INVALID_HANDLE_VALUE;
И у меня есть предупреждение:
"..warning C4047: '=' : 'HFILE' differs in levels of indirection from 'HANDLE'"
Это нормально, если я уберу предупреждение, приведя INVALID_HANDLE_VALUE к типу HFILE? Я предполагаю, что компилятор уже делает то же самое автоматически.
2 ответа
Да, когда применимы оба типа преобразования типов ("приведение") - явное и неявное - семантика явного преобразования точно такая же, как и семантика неявного преобразования.
Обратите внимание, что в вашем случае не очевидно, что неявное преобразование применимо. В WinodwsAPI HANDLE
обычно определяется как тип указателя. Вы пытаетесь преобразовать его в int
тип. Стандарт C не допускает неявное преобразование из типов указателей в int
, Это означает, что следующая декларация
HFILE stat_fh = INVALID_HANDLE_VALUE;
содержит ограничение насилия. то есть он должен быть не компилируемым. Итак, ваш вопрос на самом деле спорный (при условии, что преобразование HANDLE
для int
действительно то, что вы хотите сделать). Явное приведение - единственный вариант, который у вас есть в этом случае.
Если ваш компилятор может выполнить это преобразование неявно (с простым предупреждением), то это всего лишь причуда вашего компилятора, вообще не связанная со стандартным языком Си.
Это может сработать, но это не совсем нормально (хотя, похоже, именно этого и ожидает Microsoft; см. Ниже).
Прежде всего, ваша терминология немного отличается. Приведение - это оператор, состоящий из имени типа в скобках. Указывает явное преобразование. Не существует такого понятия, как неявное приведение или "автоматическое приведение". То, что вы называете "принудительным броском", является просто броском; то, что вы называете "автоматическим приведением", является неявным преобразованием.
HFILE
это просто другое имя для int
, Согласно документации Microsoft, HANDLE
является typedef (псевдоним) для void*
, Язык не определяет неявное преобразование из любого типа указателя в int
, В этом случае ваш компилятор позволяет вам избежать неприятностей и выдает предупреждение. Фактически, присвоение является нарушением ограничения, требующим диагностического сообщения. Ваш компилятор мог бы (и IMHO должен был) просто отклонить вашу программу с фатальным сообщением об ошибке.
Если у вас есть значение указателя, вы должны присвоить его переменной указателя того же типа.
Если вы хотите назначить HANDLE
значение для stat_fh
тогда вам следует заявить stat_fh
как HANDLE
не как int
(или даже как HFILE
что, как я уже сказал, это просто другое название int
).
Почему вы определили HFILE
как псевдоним для int
?
ОБНОВИТЬ:
я вижу это HFILE
фактически определяется Microsoft как:
typedef int HFILE;
В их документации также сказано, что HFILE
"Дескриптор файла, открытого OpenFile, а не CreateFile ". Если вы перейдете по этим ссылкам, вы увидите, что OpenFile
не рекомендуется
С другой стороны, документация для OpenFile
говорит, что файл открыт OpenFile
(который возвращает HFILE
то есть int
) следует закрыть, передав ручку CloseHandle
, который занимает HANDLE
(То есть, void*
) аргумент.
Это ужасно, и я предполагаю, что это одна из причин, по которой Microsoft решила не использовать OpenFile
,
Насколько я могу судить (хотя я не программист Windows, поэтому я мог что-то упустить), нет никаких веских причин для использования HFILE
,