Является ли доступ к int как unsigned long неопределенным поведением?

В книге под названием Programming Windows в одном из примеров у нас есть эта строка:

ReadFile (hFile, buffer, MAXREAD, &i, NULL) ;

i здесь было ранее объявлен как int, но 4-й аргумент ReadFile – это LPDWORD, что является определением типа для DWORD*, а DWORD – это определение типа для unsigned long. Это эффективная игра слов. В большинстве систем unsigned long и int имеют одинаковый размер, но я думаю, что доступ к переменной, как если бы это был какой-то другой тип, является неопределенным поведением. Это нормально? Это нормально, только если размеры одинаковые? Это УБ? Я проверил пару веб-сайтов с ошибками, и они, похоже, не перечисляют это. Я что-то упускаю?


person Ayxan Haqverdili    schedule 01.04.2020    source источник
comment
В большинстве систем unsigned long и int имеют одинаковый размер Нет, это не так. Windows является исключением здесь. Практически в любой другой 64-битной архитектуре int составляет 32 бита, а [unsigned] long — 64 бита.   -  person Andrew Henle    schedule 02.04.2020
comment
Это ошибка в книге. i должен быть объявлен как DWORD.   -  person user3386109    schedule 02.04.2020
comment
Если вы читаете до 2 ГБ (бит 31 равен нулю), проблем нет.   -  person i486    schedule 02.04.2020
comment
Обратите внимание, что в наши дни VC++ будет предупреждать об этом. Это не лучшая практика.   -  person Jonathan Potter    schedule 02.04.2020


Ответы (1)


Если DWORD определено так, как вы описываете, то код содержит нарушение ограничения, которое компилятор должен диагностировать, и стандарт больше не распространяется на поведение любого сгенерированного исполняемого файла. Неявное преобразование из int * в unsigned long *, независимо от размеров типов .

Если вы не видите сообщение об ошибке компилятора, я настоятельно рекомендую настроить параметры компилятора так, чтобы отображалось сообщение об ошибке. Некоторые компиляторы по умолчанию отображают «предупреждающее» сообщение об этой ошибке, которое может ввести неосторожных в заблуждение, заставив думать, что реальной проблемы нет.

person M.M    schedule 01.04.2020
comment
В C++ нет неявного преобразования между типами указателей, но я думаю, что в C оно есть. Не могли бы вы процитировать соответствующие части стандарта, в которых говорится, что это не определено? Некоторые люди утверждают, что это нормально, если они одного размера, другие утверждают, что это нормально, если вы не читаете больше, чем может вместить int. - person Ayxan Haqverdili; 02.04.2020
comment
@Ayxan Я добавил ссылку на другой вопрос l-l по этой теме, человек цитирует стандарт в вопросе - person M.M; 02.04.2020
comment
@Ayxan Программа недействительна (либо на C, либо на C++), поэтому здесь нечего определять. - person curiousguy; 02.04.2020
comment
компилятор должен диагностировать. Не могли бы вы дать ссылку? Я считаю, что это случай страшного IFNDR (неправильный формат, диагностика не требуется). - person IInspectable; 02.04.2020
comment
@IInspectable C не имеет неправильного формата, вы думаете о другом языке. В моем ответе есть ссылка на соответствующие стандартные цитаты о том, что это нарушение ограничения, также см. C11 5.1.1.3, в котором указано, что нарушение ограничения должно вызывать диагностику - person M.M; 02.04.2020