Вопросы, касающиеся "предупреждения C4312: 'type cast'" - PullRequest
7 голосов
/ 26 августа 2010

Это код, который у меня есть:

HWND WebformCreate(HWND hParent, UINT id)
{
    return CreateWindowEx(0, WEBFORM_CLASS, _T("about:blank"),
        WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, 100, 100, hParent,
        (HMENU)id, GetModuleHandle(NULL), 0);
}

Это предупреждение, которое я получаю:

warning C4312: 'type cast' : conversion from 'UINT' to 'HMENU' of greater size

Вот вопросы, которые у меня есть:

  1. Почему компилятор считает плохую идею приводить к большему типу?
  2. Какой лучший способ избавиться от предупреждения? (Я не хочу его отключать.)
  3. Выполнение двойного типа: (HMENU)(UINT_PTR)id избавляется от предупреждения. Почему / как?
  4. Отключение «Обнаружить проблемы 64-битной переносимости» (Wp64) также избавляет от предупреждения. Почему Wp64 не рекомендуется? Должен ли я его включить?

Ответы [ 3 ]

12 голосов
/ 26 августа 2010

Тип, который скрывается за именем HMENU, на самом деле является указателем типа.Компилятор говорит вам, что преобразование меньшего типа integer в больший тип pointer не имеет смысла, поскольку результирующее значение указателя будет "неполным", то есть биты более высокого порядка, еслиЗначение указателя будет заполнено нулями.Последнее имеет мало смысла для типов указателей.

В вашем конкретном случае это безопасно, поскольку это значение HMENU не должно быть указателем, указывающим куда-либо.Однако компилятор этого не знает, поэтому выдает предупреждение.Используйте больший integer тип в качестве промежуточного типа в приведении, и предупреждение исчезнет (вы сами это предложили), поскольку в этом случае вы делаете два приведения: меньшее целое число к большему целому, а затембольшее целое число для указателя.Меньшее целое число - большее целое число - это арифметическое преобразование , для которого имеет смысл заполнить биты старшего порядка нулями (представленное значение не изменяется), поэтому предупреждения об этом не будет.

4 голосов
/ 26 августа 2010

Вы приводите 32-битный UINT к 64-битному указателю.Это самоубийство - вы пытаетесь указать на что-то, но наполовину забыли это место!Вы абсолютно ДОЛЖНЫ взять UINT_PTR.Когда вы приводите указатель на int, поведение будет нормальным, только если int имеет тот же размер, что и указатель.Иначе, это конец времени выполнения вашего приложения благодаря нарушению прав доступа.

Редактировать:
Почему компилятор считает плохой идеей приводить к большему типу?
RE выше

Какой лучший способ избавиться от предупреждения?(Я не хочу его отключать.)
Исправить проблему.Этот код почти наверняка будет вызывать сбои.

Выполнение двойного приведения типа, подобного этому: (HMENU) (UINT_PTR) id избавляет от предупреждения.Почему / как?
Это происходит потому, что приведение UINT к UINT_PTR совершенно корректно - UINT_PTR - просто целочисленный тип, без потери данных.

Отключение «Обнаружение 64-битных проблем переносимости» (Wp64) также избавляется от предупреждения.Почему Wp64 не рекомендуется?Должен ли я его включить?
Это устарело, потому что, на самом деле, я не могу вспомнить почему.Я думаю, что это предупреждает слишком легко.Но для базового «Не приводите целочисленные типы и указатели» вы должны обязательно оставить его включенным.

2 голосов
/ 26 августа 2010

Почему компилятор считает плохую идею приводить к большему типу?

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

Каков наилучший способ избавиться от предупреждения?(Я не хочу его отключать.)

Я бы сказал, везде используйте HMENU и объявите вашу функцию как

HWND WebformCreate(HWND hParent, HMENU id)

Выполнение двойногоТип приведен так: (HMENU) (UINT_PTR) id избавляется от предупреждения.Почему / как?

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

HMENU - это тип указателя.Это не означает, что значение hMenu на самом деле является указателем, но это хак, который не позволяет вам неявно смешивать, например.HMENU и HWND (потому что HMENU и HWND - это что-то вроде struct _hMENU* и struct _hWND* соответственно, которые несовместимы, тогда как UINT s будут).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...