Вопрос

Я пытаюсь создать cairomm для gtkmm в Windows, используя mingw.Компиляция прерывается при вызове функции, у которой есть параметр, который выполняет переинтерпретацию bool в void*.

cairo_font_face_set_user_data(cobj(), &USER_DATA_KEY_DEFAULT_TEXT_TO_GLYPHS, reinterpret_cast<void*>(true), NULL);

Именно здесь код прерывается, и причина в "недопустимом переинтерпретировании из bool в void *".Почему это происходит, и как я могу изменить эту строку, чтобы заставить ее скомпилироваться?Нужна помощь

Это было полезно?

Решение

Я вижу, что это пользовательские данные, и у вас есть контроль над тем, что делается со значением, сначала приведите bool к int: reinterpret_cast<void *> (static_cast<int> (true)).Выполнение этого имеет смысл в том смысле, что параметр void * заменяет шаблонные функции в этой библиотеке ANSI-C.Все, что вам нужно, - это значение true / false.Таким образом, не должно быть никакой опасности во временном кодировании этого объекта как указателя, если он хорошо документирован как таковой.Действительно, тебе было бы лучше покончить с этим: reinterpret_cast<void *> (1) или reinterpret_cast<void *> (+true).

Другие советы

Похоже, это должно сработать, согласно стандарту.В разделе 3.9.1-7 говорится, что bool является целочисленным типом, а в разделе 5.2.10-5 говорится, что значение целочисленного типа может быть явно преобразовано в указатель с помощью reinterpret_cast .Похоже, что ваш компилятор не полностью стандартен.

Не могли бы вы обойтись без изменения значения "true" на 1?Преобразование между целыми числами и типами указателей - старая и порочная традиция в C и, следовательно, в C ++, и было бы удивительно найти компилятор, который бы этого не делал.

Или, если вам действительно нужно это сделать, попробуйте (void *)true.Затем вымойте руки.

reinterpret_cast - это плохая идея.Расскажите нам подробнее о проблеме, которую вы пытаетесь решить, и, возможно, мы найдем решение, не прибегая к переосмыслению.Почему вы хотите преобразовать bool в void *?

Единственный компилятор, который у меня есть, который жалуется на это, - GCC (MinGW с GCC 3.4.5) - и я не уверен, почему.В стандарте, по-видимому, четко указано, что это разрешено:

3.9.1 Основные типы

...

Типы bool, char, wchar_t и целочисленные типы со знаком и без знака в совокупности называются целочисленными типами.

5.2.10 Переосмыслить приведение:

...

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

Это сказало, обходной путь монжардена использования reinterpret_cast<void *> (static_cast<int> (true)) или reinterpret_cast<void *> (1) есть разумные обходные пути.

Это не удается, потому что приведение не имеет смысла - вы принимаете логическое значение true / false и просите компилятор интерпретировать это как указатель, который, грубо говоря, является ячейкой памяти.Эти двое даже отдаленно не связаны.

Попробуйте более новую версию вашего компилятора.Я только что протестировал, и это приведение работает, по крайней мере, на gcc 4.1 и выше.Однако я не знаю точно, как версии gcc соотносятся с версиями mingw.

В некоторых ситуациях крайне желательно, чтобы компилятор предупреждал или выдавал ошибку в коде типа reinterpret_cast<void*>(true), даже несмотря на то, что этот код, по-видимому, является легальным C ++.Например, это помогает при портировании на 64-разрядные платформы.

Преобразование 64-разрядного указателя в целочисленный тип, который меньше указателя (например, int или bool) часто является ошибкой:вы усекаете значение указателя.Кроме того, спецификация C ++, похоже, не гарантирует, что вы можете напрямую преобразовать указатель в меньший интегральный тип (выделено мной):

5.2.10.4.Указатель может быть явно преобразован в любой целочисленный тип достаточно большой, чтобы вместить его.Функция отображения определяется реализацией.

Аналогично, приведение меньшего интегрального типа к 64-разрядному указателю (как с reinterpret_cast<void*>(true)) также часто является ошибкой:компилятор должен чем-то заполнить верхние биты указателя;заполняется ли это нулем или расширяется знаком?Если вы не пишете низкоуровневый платформенно-ориентированный код для доступа к вводу-выводу с привязкой к памяти или DMA, вы обычно вообще не хотите этого делать, если только вы не делаете что-то хакерское (например, вставляете логическое значение в указатель).Но спецификация C ++, похоже, мало что говорит об этом случае, кроме того, что он определяется реализацией (сноска опущена):

5.2.10.5.Значение целочисленного типа или типа перечисления может быть явно преобразовано в указатель.*

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

@monjardin предложил reinterpret_cast<void*>(static_cast<int>(true)).Если причиной ошибки было несоответствие между размером интегрального типа и размером указателя, то это будет работать на большинстве 32-разрядных платформ (где оба int и void* являются 32-разрядными), но терпят неудачу на большинстве 64-разрядных платформ (где int составляет 32 бита и void* равен 64 битам).В этом случае замена int в этом выражении с целочисленным типом размером с указатель, таким как uintptr_t или DWORD_PTR (в Windows) должно сработать, поскольку преобразования между bool и разрешены целые числа размером с указатель, а также преобразования между целыми числами размером с указатель и указателями.

Более поздние версии GCC имеют следующее параметры подавления предупреждений, но не для C ++:

-Wno-преобразование int-в-указатель (только для C и Objective-C)
Подавлять предупреждения при приведении к типу указателя целого числа другого размера.

-Wno-указатель-на-int-приведение (только для C и Objective-C)
Подавлять предупреждения при приведении указателя на целочисленный тип другого размера.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top