0

Trying the convert an Integer to a Packed Record of 32 booleans.

 TUserRightsRecord = packed record
    r1:boolean;
    .
    .

 end;

yet, I am unable to find a function which convert a variable to a packed record, since the direct assignment does not work.

  • What function convert a variable ( or at least Integer ) to a Packed Record of the same bite size ?
Yordan Yanakiev
  • 2,546
  • 3
  • 39
  • 88
  • 3
    `SizeOf(Boolean)` isn't 1/8, but 1: a `Boolean` is a byte (8 bits). Anyhow: why do you need this? Why not use bitwise operations like everyone else? – Andreas Rejbrand Aug 29 '21 at 09:52
  • Can You give me some idea with an example what do You suggesting please? – Yordan Yanakiev Aug 29 '21 at 10:06
  • `const HasScreen = 1; HasSound = 2; HasKeyboard = 4; HasMouse = 8; HasInternet = 16; var ComputerProperties: Integer; // Test a bit if ComputerProperties and HasInternet = 0 then ShowMessage('You need an Internet connection.'); // Set a bit Computer := Computer or HasInternet; // Clear a bit Computer := Computer and not HasInternet;` But in Delphi, you typically use [sets](https://docwiki.embarcadero.com/RADStudio/en/Structured_Types_(Delphi)#Sets) instead. – Andreas Rejbrand Aug 29 '21 at 10:09
  • were hooping for something more elegant like typedef union of struct in c++ :'| – Yordan Yanakiev Aug 29 '21 at 11:01
  • 1
    @YordanYanakiev [to hoop](https://en.wiktionary.org/wiki/hoop#Verb_2) versus [to hope](https://en.wiktionary.org/wiki/hope#Verb). Also check [How to simulate bit-fields in Delphi records?](https://stackoverflow.com/q/282019/4299358) – AmigoJack Aug 29 '21 at 12:26
  • Delphi doesn't have bitfields. Read this http://rvelthuis.de/articles/articles-convert.html#bitfields and also do a search for Delphi bitfields and find lots of existing relevant so posts – David Heffernan Aug 29 '21 at 14:01

2 Answers2

2

Trying the convert an Integer to a Packed Record of 32 booleans.

Please note that SizeOf(Integer) = 4 while SizeOf(<packed record of 32 booleans>) = 32 because SizeOf(Boolean) = 1 (1 byte = 8 bits). You seem to be under the impression that a Boolean is a single bit; it isn't.

If that had been the case, however, you could simply have cast the integer to such a record.

(But of course it is trivially possible to write a function that "converts" an integer to a record of 32 booleans.)


The standard approach to use the bits in an integer is to use bitwise operators:

const
  HasScreen = 1;
  HasSound = 2;
  HasKeyboard = 4;
  HasMouse = 8;
  HasInternet = 16;

var
  ComputerProperties: Integer;

begin
  // Test a bit
  if ComputerProperties and HasInternet = 0 then
    ShowMessage('You need an Internet connection.');

  // Set a bit
  Computer := Computer or HasInternet;

  // Clear a bit
  Computer := Computer and not HasInternet;

In Delphi, it is more idiomatic to use sets:

type
  TComputerFeature = (cfScreen, cfSound, cfKeyboard, cfMouse, cfInternet);
  TComputerFeatures = set of TComputerFeature;

var
  Features: TComputerFeatures;

begin
  Features := [cfScreen, cfKeyboard];
  if not (cfInternet in Features) then
    ShowMessage('You need an Internet connection.');
  Include(Features, cfInternet);
  Exclude(Features, cfInternet);
end;

You may, however, easily simulate your original design approach using advanced records:

type
  TBit32 = type Integer;
  TBit32Helper = record helper for TBit32
  strict private
    function GetBit(Index: Integer): Boolean;
    procedure SetBit(Index: Integer; const Value: Boolean);
  public
    property Bit[Index: Integer]: Boolean read GetBit write SetBit;
  end;

function TBit32Helper.GetBit(Index: Integer): Boolean;
begin
  Result := (Self shr Index) and 1 <> 0;
end;

procedure TBit32Helper.SetBit(Index: Integer; const Value: Boolean);
begin
  if Value then
    Self := Self or (1 shl Index)
  else
    Self := Self and not (1 shl Index);
end;

begin
  var x: Integer := 123;
  Writeln(TBit32(x).Bit[4]); // read
  TBit32(x).Bit[6] := False; // write
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
-3

It might be enough to replace boolean with longbool

program Project1;
{$APPTYPE CONSOLE}
{$R *.res}

uses
 System.SysUtils;
var
  i: integer;
begin
 try
   i := Sizeof(boolean);
   writeln('Sizeof(boolean): ', i);

   i := Sizeof(LongBool);
   writeln('Sizeof(LongBool): ', i);

   readln(i);

 except
   on E: Exception do
     Writeln(E.ClassName, ': ', E.Message);
 end;
end.

Otherwise you may have to define your own data type as a record. Here you have to pay attention to the memory size of your data type "SizeOf". Here an excample:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TConvert=packed record
  public
    function ToString: string;
  public
    //Redefined memory. Each field has the same start address.
    case integer of
      0: (b: boolean);
      1: (G: LongBool);
      2: (i: integer);
      3: (data: array[0..3]of byte);
  end;

function TConvert.ToString: string;
begin
  //Low is left !!!
  Result := Format('[%.2x|%.2x|%.2x|%.2x]', [data[0], data[1], data[2], data[3]]);
end;

var
  i: integer;
  r: TConvert;
begin
  try
    i := Sizeof(TConvert);
    writeln('Sizeof(TConvert): ', i);

r.b := True;
writeln('boolean(true): ', r.ToString, ' ',BoolToStr(r.G, true));
r.G := false;
writeln('LongBool(false): ', r.ToString, ' ',BoolToStr(r.G, true));
r.G := True;
writeln('LongBool(true): ', r.ToString, ' ',BoolToStr(r.G, true));
r.i := 1;
writeln('LongBool(i=1): ', r.ToString, ' ',BoolToStr(r.G, true));


readln(i);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
USauter
  • 295
  • 1
  • 9