Conversion between ordinals and pointers is not portable

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Conversion between ordinals and pointers is not portable

Сообщение Flanter » 27.12.2008 18:21:44

Вообще, тема, конечно, относится к Lazarus'у, но суть всё-таки ближе к общему программированию. Дело в том, что часто бывает нужно передать числовые данные в поле типа "указатель". Например, в случае дерева (TTreeView) создаю ветку (TTreeNode) и путём явного преобразования навешиваю ей данные:

Код: Выделить всё
Node.Data := TObject(17);

Компилятор, естественно, ругается:

Код: Выделить всё
Hint: Conversion between ordinals and pointers is not portable

Или, при обратном преобразовании:

Код: Выделить всё
if Integer(Node.Data) = 17 then

получаем уже предупреждение:

Код: Выделить всё
Warning: Converting pointers to signed integers may result in wrong comparison results and range errors, use an unsigned type instead.

Собственно, вопрос: как вообще правильно передавать числовые данные через указатель? Выделять память, заносить туда число и присваивать указатель? Как-то громоздко получается, да и дополнительно потом отслеживать придётся при разрушении основного объекта, чтобы утечек не было...

Ну, или хотя бы, как отключить данные Warning и Hint? Хотя, конечно, хотелось бы разобраться в сути...

P.S. Прошу прощения за ламерский вопрос :roll:
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение Дож » 27.12.2008 19:44:29

Код: Выделить всё
// Node.Data имеет тип Pointer
Node.Data := Pointer(17);
if Cardinal(Node.Data) = 17 then

Чем не решение?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Conversion between ordinals and pointers is not portable

Сообщение Flanter » 27.12.2008 20:04:15

На

Код: Выделить всё
if Cardinal(Node.Data) = 17 then

точно так же ругается... Там проблема, как я понимаю, в том, что такой код не будет нормально компилироваться 64-битным компилятором, ведь указатели там будут тоже 64-разрядные (а Integer и Cardinal 32-разрядные, только одно знаковое, а другое - беззнаковое). Меняю Integer на Int64 или UInt64 - то же самое, только Hint превращается в Warning...
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение XProger » 27.12.2008 21:08:04

Код: Выделить всё
var
  p : PAnsiChar;
begin
  p := nil;
  Node.Data := TObject(@p[17]);
...
end;

Ничего умнее придумать не смог, а хинты и нотисы отключаются убиранием -viewnh из командной строки компилятору )
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Conversion between ordinals and pointers is not portable

Сообщение Flanter » 27.12.2008 21:19:18

Ну, с преобразованием Integer -> Pointer ещё как-то более-менее понятно, но вот с обратным преобразованием - идей у меня нет. Пока сделал две спец. функции для преобразования:

Код: Выделить всё
function ToPtr(I: PtrInt): Pointer; inline;
begin
{$HINTS OFF}
  Result := Pointer(I);
{$HINTS ON}
end;

function ToInt(P: Pointer): PtrInt; inline;
begin
{$HINTS OFF}
  Result := PtrInt(P);
{$HINTS ON}
end;

Тип используется PtrInt, он по размеру всегда эквивалентен указателю, хотя есть ли в этом смысл пока не очень ясно...

Все хинты отключать не хочется, т.к. бывают и полезные :)
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение Sergei I. Gorelkin » 28.12.2008 10:25:04

Недавно в компилятор добавили возможность избирательно управлять сообщениями, в частности, отключать ненужные хинты.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Conversion between ordinals and pointers is not portable

Сообщение Flanter » 28.12.2008 12:14:01

А это уже в 2.2.2 есть, или только в ночных сборках? Вроде в списке изменений 2.2.2 нету этого...

Вот опять же, раз уж про это речь зашла, в компиляторе теперь можно будет отключать отдельно сообщения о неиспользуемых переменных в var и отдельно сообщения о неиспользуемых параметрах функции/процедуры? Delphi вроде не сообщает, если я в процедуре не использую какие-то параметры, а FreePascal на каждый такой случай ругается хинтом...

Или, может, это тоже есть, просто я не нашёл опцию? В Lazarus IDE это можно отключить, но только для параметра Sender...
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение Sergei I. Gorelkin » 28.12.2008 12:52:22

Это ключи командной строки -vq, -vm. После -vm указываются через запятую номера сообщений, которые нужно задавить. И, кажется, после каждого номера может быть еще и буква, позволяющая его не только задавить, но и, например, сделать ошибкой. Для выяснения нужных номеров используется -vq.
Скорее всего, в 2.2.2 оно не попало.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Conversion between ordinals and pointers is not portable

Сообщение SAK » 29.12.2008 23:45:28

Можно избавиться от сообщений объявив node.data как запись с вариантами.
Код: Выделить всё
  TNode = record
    //......
    case byte of
     1: (DataInt: Integer);
     2: (DataPtr: Pointer)
   end;

Или если TNode - объект или класс, то:
Код: Выделить всё
TData = record
    case byte of
     1: (AsInt: Integer);
     2: (AsPtr: Pointer)
   end;

TNode = Class
  //.....
  Data: TData;
end;

Тогда получаем:
Код: Выделить всё
if Node.Data.AsInt = 17 then
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: Conversion between ordinals and pointers is not portable

Сообщение Flanter » 30.12.2008 06:33:18

Не, если бы это зависело от меня, то я, конечно, в своей программе объявил бы Data вообще как Integer :) Но увы, Node - это экземпляр класса TTreeNode, который является частью библиотеки Lazarus LCL, поэтому приходится искать пути обхода.
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение svk12 » 30.12.2008 16:04:44

var
PData:Pointer;

GetMem(Pdata,SizeOf(integer));
Pdata^:=17;
Node.Data:=PData;
if integer(PData^)=17 then...
svk12
постоялец
 
Сообщения: 408
Зарегистрирован: 09.06.2008 18:42:47

Re: Conversion between ordinals and pointers is not portable

Сообщение Flanter » 30.12.2008 16:16:42

В принципе, да - такой вариант самый правильный. Я знал, что всё им и закончится :)

Ну что делать - придётся дописывать ещё код для освобождения памяти при каждом разрушении сотни объектов Node...
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение SAK » 30.12.2008 23:16:26

Flanter писал(а):Node - это экземпляр класса TTreeNode

Тогда:
Код: Выделить всё
if (p-pchar(0))=17 then

Компилятор ошибок не видит, оптимизатор выбросит лишние операции :)
По крайней мере у меня ничего не пишет по этому поводу.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: Conversion between ordinals and pointers is not portable

Сообщение Flanter » 16.11.2009 10:06:32

А подниму-ка я старую тему :)

В новом Lazarus'е (0.9.28[.2]) в опциях проекта есть закладка Messages, которая позволяет отключать отдельные сообщения (опция -vm, о которой говорил Сергей Горелкин). А нет ли соответствующей директивы компилятора? Нынешние {$HINTS OFF} и {$HINTS ON} воздействуют на все подсказки, а вот чтобы конкретную вырубить? То ли я плохо искал, то ли нет её, не нашёл, в общем...

Нужно это бывает в том случае, если один модуль, генерирующих конкретный хинт, используется в нескольких проектах. Тогда отключать этот хинт приходится в свойствах каждого проекта. А так вставил бы в начало директиву - и нет проблем...
Flanter
новенький
 
Сообщения: 42
Зарегистрирован: 03.11.2007 22:15:54

Re: Conversion between ordinals and pointers is not portable

Сообщение MageSlayer » 21.11.2009 00:50:20

Собственно тип PtrInt, объявленный в system, для этого и предназначен.
MageSlayer
постоялец
 
Сообщения: 216
Зарегистрирован: 07.09.2006 12:30:44

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru