← →
ZV ©
(2011-01-26 17:04)
[0]
Как в Delphi преобразовать 2 значения Byte в Word. На Си делаю побитовый сдвиг и наложение маски а как это сделать в Delphi? Может есть какая функция или делать так же как и на Си. Может кто покажет пример?
← →
sniknik ©
(2011-01-26 17:19)
[1]
> Может кто покажет пример?w:= b;
← →
Германн ©
(2011-01-26 17:21)
[2]
1. Word1:=Byte1+(Byte2 shl 8)
2. type
TMyWord = packed record
case Integer of
0 : (Byte1, Byte2 : Byte);
1 : (Word1 : Word);
end;
← →
12 ©
(2011-01-26 17:33)
[3]
var
w:Word;
b1, b2:Byte;
begin
b1 := 0;
b2 := 1;
asm
push ax
mov al, b1
mov ah, b2
mov w, ax
pop ax
end;
ShowMessage( IntToStr(w) );
← →
sniknik ©
(2011-01-26 17:55)
[4]
и еще на конкурс извращенцев…procedure TForm1.Button1Click(Sender: TObject);
var
w: Word;
b: byte absolute w;
begin
w:= 0;
b:= $FF;
ShowMessage(IntToStr(w));
end;
← →
Игорь Шевченко ©
(2011-01-26 18:17)
[5]
> Может есть какая функция или делать так же как и на Си.
а как на С сделано ?
← →
Германн ©
(2011-01-26 18:20)
[6]
> sniknik © (26.01.11 17:55) [4]
>
> и еще на конкурс извращенцев…
Не проходит по условию. Нужно два байта.
← →
ZV ©
(2011-01-26 19:11)
[7]
> а как на С сделано ?
unsigned int word;
unsigned char Ah, Bl;
Word=Ah;
word=(word<<8)|Bl;
То же на Delphi — Word1:=Byte1+(Byte2 shl 8)
(1 вариант от Германн)
нормально работает
← →
DiamondShark ©
(2011-01-26 19:26)
[8]
мне бы ваши проблемы
← →
sniknik ©
(2011-01-26 19:28)
[9]
> Не проходит по условию. Нужно два байта.
блин, упустил почему то, и получается фигню нес…
тогда такvar
w: Word;
b: array[0..1] of byte absolute w;
begin
b[0]:= 1;
b[1]:= 1;
ShowMessage(IntToStr(w));
end;
← →
DiamondShark ©
(2011-01-26 19:36)
[10]
const
Q: array[byte,byte] of word = (
(0,1,2,3 … 255),
(256, 257 … 511)
…
(65280, … ,65535)
);
w := Q[b1, b2];
← →
sniknik ©
(2011-01-26 19:48)
[11]
ну или тот же код что в [9] по мотивам asm ([3])var
w: Word;
begin
asm
mov byte ptr w[0], $01
mov byte ptr W[1], $01
end;
ShowMessage(IntToStr(w));
end;
← →
Студент
(2011-01-27 04:42)
[12]
Занятно…))
А поясните пожалуйста «case Integer of» в record (кстати packed ни разу не пригодился, остаётся тож самое)?
А какой будет самым быстрым? Случайно не [10]?
← →
KilkennyCat ©
(2011-01-27 04:55)
[13]
strtoint(inttostr(b1) +inttostr(b2))
← →
Студент
(2011-01-27 05:39)
[14]
Ну… Вот с «Hex» такое бы сработало…
← →
Inovet ©
(2011-01-27 05:45)
[15]
> [12] Студент (27.01.11 04:42)
> А какой будет самым быстрым?
Самый быстрый, который ничего не делает — с рекордом и с массивом, а [10] — это явный кандидат в победители на конкурсе извращенцев.:)))
← →
Студент
(2011-01-27 06:50)
[16]
Скомпилировал [10]… Неправильно считает… Нужно как-то по другому заполнять масив…
Про [11] говорит мол «Invalid combination of opcode and operands» если пытаться пременную подставить…((
У [13] результат неверный… Нужно через Hex: Word1:=HexToInt(IntToHex(Byte2, 2)+IntToHex(Byte1, 2));
← →
Студент
(2011-01-27 06:51)
[17]
Чуть не забыл:
procedure TForm1.Button8Click(Sender: TObject);
var i: Integer; S: String;
begin
S:="((0, ";
For i:=1 To 65534 Do
Begin
If (i mod 256)=0 Then
S:=S+"),"#13#10"("+IntToStr(i)+", "
Else
If ((i+1) mod 256)=0 Then
S:=S+IntToStr(i)
Else
S:=S+IntToStr(i)+", ";
If (i mod 100)=0 Then
S:=S+#13#10;
End;
S:=S+"65535));";
Memo1.Text:=S;
end;
Да, я дурак….. %))
← →
han_malign
(2011-01-27 08:41)
[18]
> А какой будет самым быстрым? Случайно не [10]?
— случайно:
Германн © (26.01.11 17:21) [2]
1. Word1:=Byte1+(Byte2 shl
— т.к. нет лишних обращений к памяти, а таких регистровых операций — современные CPU хавают по десятку за такт…
Недаром девиз Мелкомягких — «Все что можно пересчитать — лучше не хранить»…
← →
RWolf ©
(2011-01-27 09:25)
[19]
> Inovet © (27.01.11 05:45) [15]
> > [12] Студент (27.01.11 04:42)> А какой будет самым быстрым?
> Самый быстрый, который ничего не делает — с рекордом и с
> массивом,
Самый быстрый — это сдвиг + OR.
← →
Игорь Шевченко ©
(2011-01-27 10:30)
[20]
> — т.к. нет лишних обращений к памяти, а таких регистровых
> операций — современные CPU хавают по десятку за такт…
обычно подобные утверждения подкрепляются тестовыми измерениями.
> Недаром девиз Мелкомягких — «Все что можно пересчитать —
> лучше не хранить»…
кто не работает — не ест, ты спутал, батя
← →
Германн ©
(2011-01-27 15:10)
[21]
> han_malign (27.01.11 08:41) [18]
>
>
> > А какой будет самым быстрым? Случайно не [10]?
>
> — случайно:
> Германн © (26.01.11 17:21) [2]
> 1. Word1:=Byte1+(Byte2 shl
>
> — т.к. нет лишних обращений к памяти, а таких регистровых
> операций — современные CPU хавают по десятку за такт…
>
Хорошо подумал прежде чем написать такую чушь?
Нахрена нужны какие-то «операции» для того, чтобы всего лишь расположить два байта рядом в памяти???
← →
han_malign
(2011-01-27 17:40)
[22]
> ты спутал, батя
— я изредка брежу, но редко путаю:program hilo_word;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
Windows, SysUtils;
const repeatCount = 10;
type
TLoHiWord = packed record
case Integer of
0 : (Lo, Hi : Byte);
1 : (value : Word);
end;
PByteArray = ^TByteArray;
TByteArray = array[word]of byte;
PWordArray = ^TWordArray;
TWordArray = array[word]of TLoHiWord;
var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);
end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
WriteLn(title:10,": ", _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, ".", _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, " x 100ns" );
end;
var rgwLookup: array[byte,byte]of word;
var
pbl, pbh: PByteArray;
pw: PWordArray;
alloc, base, i, cnt: cardinal;
si: TSystemInfo;
begin
alloc:= 0;
if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
if( alloc = 0 )then alloc:= 1024*1024*1024;
GetSystemInfo(si);
inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);
pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
if( pbl = nil )then begin
Writeln("Alloc failed - ", GetLastError());
end;
//prepare lookup table
for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i].value:= i;
base:= alloc div 4;
Write("GO"#13);
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do PWordArray(pbl)[i].value:= Random(65536);
Write(cnt:2,#13);
end;
_stopProfile("Random");
pbh:= PByteArray(@pbl[base]);
pw:= PWordArray(@pbh[base]);
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= (pbh[i] shl 8) or pbl[i];
Write(cnt:2,#13);
end;
_stopProfile("Combine");
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do with pw[i] do begin
lo:= pbl[i];
hi:= pbh[i];
end;
Write(cnt:2,#13);
end;
_stopProfile("Direct");
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= rgwLookup[pbl[i], pbh[i]];
Write(cnt:2,#13);
end;
_stopProfile("Lookup");
_startProfile;
for cnt:= 1 to repeatCount do begin
move(pbl^, pw^, base*2);
Write(cnt:2,#13);
end;
_stopProfile("just copy");
VirtualFree(pbl, 0, MEM_RELEASE);
end.
——————————————————
Random: 0. 106406250 x 100ns
Combine: 0. 52500000 x 100ns
Direct: 0. 55781250 x 100ns
Lookup: 0. 91406250 x 100ns
just copy: 0. 33125000 x 100ns
← →
Игорь Шевченко ©
(2011-01-27 18:12)
[23]
Я несколько изменил порядок тестов
Combine: 0. 13437500 x 100ns
just copy: 0. 7031250 x 100ns
Lookup: 0. 15156250 x 100ns
Random: 0. 25625000 x 100ns
Direct: 0. 13281250 x 100ns
← →
Игорь Шевченко ©
(2011-01-27 18:13)
[24]
program BtoWProfile;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
Windows,
SysUtils;
const repeatCount = 10;
type
TLoHiWord = packed record
case Integer of
0 : (Lo, Hi : Byte);
1 : (value : Word);
end;
PByteArray = ^TByteArray;
TByteArray = array[word]of byte;
PWordArray = ^TWordArray;
TWordArray = array[word]of TLoHiWord;
var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);
end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
WriteLn(title:10,": ", _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, ".", _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, " x 100ns" );
end;
var rgwLookup: array[byte,byte]of word;
var
pbl, pbh: PByteArray;
pw: PWordArray;
alloc, base, i, cnt: cardinal;
si: TSystemInfo;
begin
alloc:= 0;
if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
if( alloc = 0 )then alloc:= 256*1024*1024;
GetSystemInfo(si);
inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);
pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
if( pbl = nil )then begin
Writeln("Alloc failed - ", GetLastError());
end;
//prepare lookup table
for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i].value:= i;
base:= alloc div 4;
Write("GO"#13);
pbh:= PByteArray(@pbl[base]);
pw:= PWordArray(@pbh[base]);
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= (pbh[i] shl 8) or pbl[i];
Write(cnt:2,#13);
end;
_stopProfile("Combine");
_startProfile;
for cnt:= 1 to repeatCount do begin
move(pbl^, pw^, base*2);
Write(cnt:2,#13);
end;
_stopProfile("just copy");
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= rgwLookup[pbl[i], pbh[i]];
Write(cnt:2,#13);
end;
_stopProfile("Lookup");
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do PWordArray(pbl)[i].value:= Random(65536);
Write(cnt:2,#13);
end;
_stopProfile("Random");
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do with pw[i] do begin
lo:= pbl[i];
hi:= pbh[i];
end;
Write(cnt:2,#13);
end;
_stopProfile("Direct");
VirtualFree(pbl, 0, MEM_RELEASE);
end.
← →
han_malign
(2011-01-27 18:27)
[25]
> Lookup: 0. 15156250 x 100ns
> Random: 0. 25625000 x 100ns
— молодец, но даже учитывая, что тест всегда обращается к rgwLookup[0, 0], поскольку память инициализирована нулями — таблица все равно самый плохой вариант…
← →
han_malign
(2011-01-27 18:33)
[26]
и естественно — все Page Fault достались Combine…
← →
Игорь Шевченко ©
(2011-01-27 18:39)
[27]
> и естественно — все Page Fault достались Combine…
отсюда возникает вопрос — что тестируем ?
← →
Inovet ©
(2011-01-27 19:54)
[28]
> [18] han_malign (27.01.11 08:41)
> [19] RWolf © (27.01.11 09:25)
> Самый быстрый — это сдвиг + OR.
Это в произвольном случае, а когда надо всё время и так и так обращаться, то лучше ничего не делать а сразу организовать хранение рядом, я об этом говорил. Хотя как оно там будет на каком железе должно
> [20] Игорь Шевченко © (27.01.11 10:30)
> подкрепляются тестовыми измерениями
← →
han_malign
(2011-01-28 09:02)
[29]
> отсюда возникает вопрос — что тестируем ?
— вы ничего не тестируете, поскольку подбираете условия по каким то выгодным вам критериям…
Между прочим, если совсем исключить из теста Combine инициализацию страниц памяти нулем при первом обращении(заполнив Random-ом всю выделенную память, а не первую половину) — отрыв еще больше увеличивается…
З.Ы. Самое прикольное это — rgwLookup[Hi, Lo] — как по вашему вычисляется смещение, если адресная арифметика поддерживает только масштабы 1, 2, 4, 8…
← →
12 ©
(2011-01-28 09:44)
[30]
> han_malign (27.01.11 17:40) [22]
> Игорь Шевченко © (27.01.11 18:13) [24]
вы — маньяки
← →
han_malign
(2011-01-28 09:45)
[31]
И о главном: почему опасно пользоваться приведением типа для доступа к битовым полям(в Delphi, в C — все порадужней), и когда таблица таки выгодна…
(посвящается структуре TRGBQuad)program hilo_word;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
Windows, SysUtils;
const repeatCount = 10;
type
TLoHiWord = packed record
case Integer of
0 : (Lo, Hi : Byte);
1 : (value : Word);
end;
PLoHiWord = ^TLoHiWord;
PByteArray = ^TByteArray;
TByteArray = array[word]of byte;
PWordArray = ^TWordArray;
TWordArray = array[word]of word;
var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);
end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
WriteLn(title:10,": ", _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, ".", _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, " x 100ns" );
end;
function TRANSFORM(val: word): word;
begin
//ну пускай будет BGR16 в BGR15
Result:= val and $1F or (val shr 1) and $7FE;
end;
const _title: array[0..2]of string = ("Combine", "Cast", "Map");
var rgwLookup: array[byte,byte]of word;
var
pbl, pbh: PByteArray;
pw: PWordArray;
alloc, base, i, cnt: cardinal;
si: TSystemInfo;
_b2w: TLoHiWord;
choice: integer;
_hitChoice: array[0..2]of integer;
fdwDoneChoice: LongWord;
begin
alloc:= 0;
if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
if( alloc = 0 )then alloc:= 1024*1024*1024;
GetSystemInfo(si);
inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);
pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
if( pbl = nil )then begin
Writeln("Alloc failed - ", GetLastError());
end;
//prepare lookup table
for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i]:= TRANSFORM(i);
base:= alloc div 4;
Write("GO"#13);
_startProfile;
for i:= 0 to base*2 - 1 do PWordArray(pbl)[i]:= Random(65536);
_stopProfile("Random");
pbh:= PByteArray(@pbl[base]);
pw:= PWordArray(@pbh[base]);
FillChar(_hitChoice, sizeof(_hitChoice), 0);
fdwDoneChoice:= 0;
while( fdwDoneChoice <> 7 )do begin
//дабы никому не пришло в голову упрекнуть меня в предвзятости
choice:= Random(3);
inc(_hitChoice[choice]);
if( _hitChoice[choice] > 2 )then fdwDoneChoice:= fdwDoneChoice or (1 shl choice);
_startProfile;
for cnt:= 1 to repeatCount do begin
case(choice)of
0: for i:= 0 to base - 1 do pw[i]:= TRANSFORM((pbh[i] shl 8) or pbl[i]);
1: for i:= 0 to base - 1 do with _b2w do begin
lo:= pbl[i];
hi:= pbh[i];
pw[i]:= TRANSFORM(value);
end;
2: for i:= 0 to base - 1 do pw[i]:= rgwLookup[pbl[i], pbh[i]];
end;
Write(cnt:2,#13);
end;
_stopProfile(_title[choice]);
end;
VirtualFree(pbl, 0, MEM_RELEASE);
end.
—————————————
Cast: 0. 274687500 x 100ns
Map: 0. 90000000 x 100ns
Combine: 0. 141250000 x 100ns
Combine: 0. 141250000 x 100ns
Cast: 0. 275000000 x 100ns
Cast: 0. 275000000 x 100ns
Map: 0. 89843750 x 100ns
Combine: 0. 141250000 x 100ns
Map: 0. 90000000 x 100ns
← →
RWolf ©
(2011-01-28 10:20)
[32]
C:>hilo_word.exe 67108864
Random: 0. 2187500 x 100ns
Combine: 0. 10781250 x 100ns
Combine: 0. 10625000 x 100ns
Combine: 0. 10468750 x 100ns
Cast: 0. 19218750 x 100ns
Combine: 0. 10468750 x 100ns
Map: 0. 18593750 x 100ns
Combine: 0. 10468750 x 100ns
Cast: 0. 20156250 x 100ns
Map: 0. 18593750 x 100ns
Map: 0. 18437500 x 100ns
Cast: 0. 19687500 x 100ns
Атлон64 3000+. Налицо двукратный выигрыш shl-or.
И почему вдруг в Дельфи опасно пользоваться приведением типа, и чем Дельфи в этом смысле отличается от Си?
← →
RWolf ©
(2011-01-28 10:28)
[33]
или смысл в том, чтобы загнать тест в свопы?
← →
uniken1 ©
(2011-01-31 08:04)
[34]
> и еще на конкурс извращенцев…
Интересно на какое место попадет функция
TwoByteToWord из Indy модуль(IdGlobal)? Собственный динамический массив с изменением размера и с двойным преобразованием.
Появляются подозрения, что Indy не очень-то оптимальна по производительности.
← →
Anatoly Podgoretsky ©
(2011-01-31 08:48)
[35]
> uniken1 (31.01.2011 08:04:34) [34]
Лучше подумать, что курили разработчки и почему с нами не поделились
← →
sniknik ©
(2011-01-31 09:28)
[36]
> uniken1 © (31.01.11 08:04) [34]
если бы не динамический массив… не все так страшно, хотя предпочел бы типа (соглашения о передаче параметров из функции вроде неизменны) —
function TwoByteToWord(AByte1, AByte2: Byte): Word;
asm
mov al, AByte1
mov ah, AByte2
end;
> почему с нами не поделились
главный вопрос…
← →
Anatoly Podgoretsky ©
(2011-01-31 11:22)
[37]
> sniknik (31.01.2011 09:28:36) [36]
Правильно, главный, их код нам и нафиг не нужен.
|
|
|
Пожалуйста, выделяйте текст программы тегом [сode=pas] … [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как «свернуть» программу в трей.
3. Как «скрыться» от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
… (продолжение следует) …
Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.
Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка — 60 дней. Последующие попытки бан.
Мат в разделе — бан на три месяца…
byte+byte=word
, преобразование 2-х переменных byte в word
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Добрый день!!! Столкнулся с проблемой преобразования двух переменных типа byte в одну типа word. Заранее спасибо. |
Булат Шакиров |
|
Слово := Старший_байт*256+Младший_байт; |
Coala |
|
Ну если у тебя первый ТВОЙ байт должен быть старшим, то можно так Сообщение отредактировано: Coala — 04.04.06, 08:03 |
Albinos_X |
|
Full Member Рейтинг (т): 16 |
… W:=(B1 Shl + B2; … Сообщение отредактировано: Albinos_X — 04.04.06, 08:06 |
intaari |
|
Оззя Сообщение отредактировано: intaari — 04.04.06, 08:08 |
Mechanic |
|
var Hb,LB: byte; W: word; absolute Hb; begin Hb := $12; Lb := $34; writeln(‘$’+IntToHex(W,4)); end; |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Delphi: Общие вопросы
- Следующая тема
[ Script execution time: 0,0457 ] [ 16 queries used ] [ Generated: 13.04.23, 20:57 GMT ]
These functions are useful:
function MakeWord(low, high: char): word;
begin
result := byte(high) shl 8 + byte(low);
end;
function MakeWord(low, high: byte): word;
begin
result := high shl 8 + low;
end;
However I am wondering if these kinds of functions (could be implemented differently) already exist somewhere (not in a windows api specific file, but rather a cross platform RTL function).
Example use case: take the two characters GT and make a WORD result out of it.
MakeWord('G','T');
I find this more readable than inserting SHL/SHR AND/OR hex operations and other hacks in the code that do not describe what the code is doing… so surely these functions exist somewhere already? Or do people roll their own in their applications?
Or something like:
var x: word;
begin
lo(x) := byte('G');
hi(x) := byte('T');
end;
However, that will not work as the left side cannot be assigned to: but it is more readable, than some other solutions, IMO.
I think I have seen LoWord and HiWord functions too (or LoByte, HiByte) but usually in read only cases. What about writing to the hi and lo?
#delphi #delphi-7
#delphi #delphi-7
Вопрос:
Я разрабатываю проект с помощью Delphi и хочу преобразовать массив байтов в строковый тип. Как я могу это сделать?
Примеры кодов C #:
private void ListenerOnDataTransmit(DataTransmitEventArgs e)
{
transmittedMsg = BitConverter.ToString(e.TransmittedBytes, 0, e.TransmittedBytes.Length);
try { Invoke(new EventHandler(UpdateTransmittedMessagesListView)); }
catch { }
}
Комментарии:
1. Вы забыли сказать нам, что вы подразумеваете под «преобразованием массива байтов в строку». Существует несколько различных интерпретаций, все разумные: (1) обработайте массив байтов как ASCII и получите кодируемый им текст; (2) обработайте массив байтов как UTF8 и получите кодируемый им текст; (3) получите необработанное шестнадцатеричное представление массива данных; (4) получите необработанныйдвоичное представление массива данных; и т.д. В последних случаях вы хотите сгруппировать цифры?
Ответ №1:
BitConverter.ToString()
Метод «Преобразует числовое значение каждого элемента указанного массива байтов в эквивалентное шестнадцатеричное строковое представление». Вы можете сделать то же самое вручную в Delphi 7, используя SysUtils.IntToHex()
функцию в цикле, например:
uses
..., SysUtils;
var
bytes: array of byte;
s: string;
i: Integer;
begin
bytes := ...;
s := '';
if bytes <> nil then
begin
s := IntToHex(bytes[0], 2);
for i := 1 to High(bytes) do
s := s '-' IntToHex(bytes[i], 2);
end;
end;
Комментарии:
1. Совершенно допустимо, но (очень) неэффективно для длинных буферов из-за постоянного перераспределения строки.
2. @AndreasRejbrand Да, есть много разных способов подойти к этому. Выше приведен только один пример.
3. Верно. И для небольших буферов это, безусловно, достаточно хорошо, так что 1.
4. По крайней мере, теперь у нас есть действительно хороший Q amp; A, который мы можем использовать как канонический для закрытия дубликатов.
5. @RemyLebeau Спасибо, я искал это.
Ответ №2:
Я подозреваю, что вам нужна функция, которая принимает массив байтов (или необработанный указатель на байты) и возвращает строку, содержащую данные в шестнадцатеричной форме.
Для этого я всегда использую следующую свою процедуру:
function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
const
HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
var
i: Integer;
begin
if ALen = 0 then
begin
Result := '';
Exit;
end;
SetLength(Result, 3 * ALen - 1);
Result[1] := HexDigits[ABuf^ shr 4];
Result[2] := HexDigits[ABuf^ and $0F];
for i := 1 to ALen - 1 do
begin
Inc(ABuf);
Result[3*i 0] := ' ';
Result[3*i 1] := HexDigits[ABuf^ shr 4];
Result[3*i 2] := HexDigits[ABuf^ and $0F];
end;
end;
type
TByteArray = array of Byte;
function BytesToString(ABytes: TByteArray): string; overload;
begin
Result := BytesToString(PByte(ABytes), Length(ABytes));
end;
Первая перегрузка принимает необработанный указатель и длину, в то время как вторая перегрузка принимает динамический массив байтов.
Это очень быстрая реализация, поскольку я не использую конкатенацию строк (которая требует постоянных перераспределений кучи).
Приведенный выше код был написан специально для старого компилятора Delphi 7 и RTL. Современная версия будет выглядеть примерно так:
function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
const
HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
var
i: Integer;
begin
if ALen = 0 then
Exit('');
SetLength(Result, 3 * ALen - 1);
Result[1] := HexDigits[ABuf[0] shr 4];
Result[2] := HexDigits[ABuf[0] and $0F];
for i := 1 to ALen - 1 do
begin
Result[3*i 0] := ' ';
Result[3*i 1] := HexDigits[ABuf[i] shr 4];
Result[3*i 2] := HexDigits[ABuf[i] and $0F];
end;
end;
function BytesToString(ABytes: TArray<Byte>): string; overload;
begin
Result := BytesToString(PByte(ABytes), Length(ABytes));
end;
Приведенный выше код группирует каждый байт с использованием символа пробела. Конечно, вы можете этого не хотеть, но выполнение этого без группировки — более простая задача, поэтому я оставлю это как упражнение.
Комментарии:
1. Честно говоря, я действительно чесал голову, когда увидел
3 * ALen
… То есть, пока я не увидел пробел.2.
PByte
Математика ptr на основе IIRC недоступна в Delphi 7, поэтому я заменил ее еще несколькими методами старой школы.
Форум программистов Vingrad
Модераторы: Poseidon, Snowy, bems, MetalFan |
Поиск: |
|
Два Byte в Word Не сложение!!! |
Опции темы |
RinOSpro |
|
||
Unregistered
|
Есть скажем 2 байтовых переменных и переменная Word и нужно пометить один байт в старший разряд а другой в младший разряд. (не сложить!);
Есть ли другие споссобы? |
||
|
|||
Snowy |
|
||
Эксперт Профиль
Репутация: 192
|
Логическими операциями или вариантной записью.
|
||
|
|||
Beltar |
|
||
Опытный Профиль Репутация: 3
|
Еще один извращенский вариант использовать указатели. Но это для справки, т. к. варианты Snowy короче. ——————— Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. (с) я, хотя может и нет |
||
|
|||
Virtuals |
|
||
Опытный Профиль Репутация: 3
|
извращения с волшебной палочкой ABSOLUTE но возможностей куча. тоесть вообще никаких операций не нужно делать ни сдвигов ни умножения, а просто обьявить переменные в одних и тех же местах
Это сообщение отредактировал(а) Virtuals — 19.6.2008, 13:43 |
||
|
|||
Virtuals |
|
||
Опытный Профиль Репутация: 3
|
. Это сообщение отредактировал(а) Virtuals — 19.6.2008, 13:35 |
||
|
|||
Snowy |
|
||
Эксперт Профиль
Репутация: 192
|
Никак. |
||
|
|||
RinOSpro |
|
||
Unregistered
|
Snowy ты уверен что это точнее я так делал… но отказался в пользу умножения. тк. что то это глючило помоему хотя хз… В общем спасибо! Щас выберу оптимальный вариант. Добавлено через 10 минут и 27 секунд |
||
|
|||
Snowy |
|
||
Эксперт Профиль
Репутация: 192
|
Моя запись идентична твоей. Только работает быстрее и работает правильно. |
||
|
|||
Alexeis |
|
||
Амеба Профиль
Репутация: 109
|
Директиву absolute, не желательно использовать, так как это усложнит перенос на Delphi.NET. По крайней мере Codeger не рекомендует ее использовать. Вообще, красивее будет так
Дело в том что чисто логически b1 shl 8 должен дать 0, потому что операнд 8ми битовый, но компилятор оптимизирует вычисления расширяя байтовые операнды до 32х битовых слов, потому это будет работать. ——————— Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
||
|
|||
|
Правила форума «Delphi: Общие вопросы» | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) |
0 Пользователей: |
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |