Typecasting кардинал к одиночному

и Cardinal и Single являются 4 байт / 32-битными типами данных, но когда я печатаю их друг другу, я получаю Invalid Typecast ошибка Delphi 10.1 (Берлин).

lSingleVar := Single(lCardinalVar);

Я не говорю о преобразование между двумя типами, так как это будет хранить только 23 бита кардинальных данных (фракционная часть один тип данных). Мне нужно сохранить минимум 30 бит данных в Single переменной. У меня есть веские причины для этого (типа не может быть изменено), о котором я с удовольствием расскажу подробнее.

как мне typecast a Single переменной?

4 ответов


Я бы сделал так:

lSingleVar := PSingle(@lCardinalVar)^;

и в противоположном направлении это будет:

lCardinalVar := PCardinal(@lSingleVar)^;

Я не могу придумать более прямого способа достичь того, что вы просите. На мой взгляд, это имеет то преимущество, что не требует каких-либо определений типа или функции.


вы можете использовать запись варианта для доступа к той же базовой памяти:

type
  TConverter = record
  case integer of
    0 : (c: cardinal);
    1 : (s: single);
  end;

а затем используйте его так:

var
  converter: TConverter;
  lCardinalVar: cardinal;
  lSingleVar: single;

  converter.c := lCardinalVar;
  lSingleVar := converter.s;

или с одной строкой typecast, как это:

lSingleVar := TConverter(lCardinalVar).s

варианты деталей в записях


вы можете написать такую функцию:

function ConvertCardinalToSingle(value: Cardinal): Single;
var AsSingle: Single absolute value;
begin
  Result := AsSingle;
end;

здесь мы используем absolute ключевое слово, которое означает: переменная value и AsSingle выделить одну и ту же память. Это ключевое слово считается устаревшим многими, и оно определенно "небезопасно", но оно использует его (мне нравится использовать его в обработчиках событий для приведения отправителя к нужному мне типу, но сначала все равно проверяет).

вам не нужно писать функцию, вы можете просто иметь эти две переменные, указывающие на одно место в некоторых точка.


вы можете использовать move для копирования необработанных байтов:

Assert(SizeOf(CardinalVar) = SizeOf(SingleVar);
Move(CardinalVar, SingleVar, SizeOf(CardinalVar));