Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как правильно массив байт привести к integer? [D7, WinXP]


Страницы:   1 2

Aleksandr. ©   (2005-02-09 14:38:00) 

Читаю буфер из стрима, в который было записано 1 размером в integer:

var
 Buf : array of byte;
 i   : integer;
begin
 SetLength(Buf,SizeOf(Integer));
 Stream.Read(Buf[0],Length(buf));
 Move(Buf[0],i,Length(Buf);

в Buf после чтения находится (0,0,0,1), но такое приведение к integer дает в результате совершенно дикое число. Как буфер правильно привести к integer?


SammIk   (2005-02-21 07:04:00) [1]

С чегоже ломать-то?
Комент поставил и усе.
И что такое дотнет не знаю и знать не хочу.


Anatoly Podgoretsky   (2005-02-20 23:20:00) [2]

И будешь голову ломать над этим bswap скажем в .NET


SammIk   (2005-02-20 22:24:00) [3]

Товарищь Верг, ну вы и выпендрились же)))
А чем bswap не то?


Verg   (2005-02-20 22:07:00) [4]


> в Buf после чтения находится (0,0,0,1), но такое приведение
> к integer дает в результате совершенно дикое число. Как
> буфер


Сетевой порядок байтов. Любая многобайтовая переменная передается в порядке уменьшения старшинства байтов в ней.

В данном случае переменная четырехбайтовая.

uses Winsock;

Stream.Read(I, sizeof(I));
I := ntohl( I );


ntohl - Network To Host byte order convertion for Long


SammIk   (2005-02-20 21:58:00) [5]

Вот так-так


begin...end   (2005-02-09 18:56:00) [6]

Кстати, я забыл про команду ассемблера BSWAP, как раз подходящую для этого случая.

var
 I: Integer;
begin
 I := ...;
 asm
   MOV EAX,I
   BSWAP EAX
   MOV I,EAX
 end
 ...
end.


Простенько и со вкусом :-)


Aleksandr.   (2005-02-09 15:34:00) [7]

begin...end ©  :
Я же объяснил, что в поток могут записывать две программы - старая версия пишет integer, а новая - только integer, в то время как приемник для чтения потока один общий. Спасибо за код.


begin...end   (2005-02-09 15:23:00) [8]

> Aleksandr.   (09.02.05 15:14) [12]

Как в буфере может оказаться только четыре байта, если буфером будет переменная типа записи TRec?


begin...end   (2005-02-09 15:17:00) [9]

> Aleksandr.   (09.02.05 14:54) [8]

1.

for I := 0 to 3 do
 CopyMemory(Pointer(Cardinal(@NewValue) + I), Pointer(Cardinal(@OldValue) + 3 - I), 1)

2.

NewValue := ((OldValue and $FF000000) shr 24) or ((OldValue and $FF0000) shr 16) or ((OldValue and $FF00) shr 8) or (OldValue and $FF)


Aleksandr.   (2005-02-09 15:14:00) [10]

Ega23 ©  :
Ну не могу я их порекордно читать... Если в буфере окажется только четыре байта, а я буду ждать 12 байт, для соединения это в конечном итоге закончится таймаутом...


Ega23   (2005-02-09 15:06:00) [11]

Если ты пишешь данные в буфер по-рекордно, то и читай их оттуда по-рекордно, тогда никаких проблем не будет.
А вот если их оттуда по-байтово читать, то можно на грабли нарваться...


Aleksandr.   (2005-02-09 15:03:00) [12]

Ega23 © :
Епрст. Как все сложно-то. Спасибо! Только еще вопрос: а как будет располагаться в буфере такое:

type
 TRec = record
   i1 : integer;
   i2 : integer;
   i3 : integer;
 end;
var
 R : TRec;
begin
 Stream.Write(R,SizeOf(r))

В смысле, i1, i2, i3 там будут последовательно, но с перевернутыми байтами внутри числа, или еще и сам порядок полей будет i3, i2, i1?


Ega23   (2005-02-09 14:59:00) [13]

Если ты по-байтно потом к этому буферу будешь обращаться, то, конечно, сдвигать надо. А так - читай сразу integer.

Но если сдвигать, то вот функция. Честно содрана с не_помню_чьего исходника. Переводила представление числа в I386 для MAC:


function Swap32(Value: Integer): Integer;
var
b1, b2, b3, b4 : Integer;

begin
b1 := Value and 255;
b2 := (Value shr 8) and 255;
b3 := (Value shr 16) and 255;
b4 := (Value shr 24) and 255;
b1 := b1 shl 24;
b2 := b2 shl 16;
b3 := b3 shl 8;
Result := b1 or b2 or b3 or b4;
end;


Aleksandr.   (2005-02-09 14:54:00) [14]

Ega23 © :
ох, эти операции сдвига, млин... туго у меня с ними. Как развернуть i в нужную сторону после приведения?


Aleksandr.   (2005-02-09 14:52:00) [15]

Точнее, старая программа писала в буфер record из трех integer. Если проблема в том, что в буфере поменяны местами байты, боюсь, как бы не оказалось, что при записи такого рекорда там весь буфер задом наперед окажется.


begin...end   (2005-02-09 14:52:00) [16]

> Aleksandr.   (09.02.05 14:38)

У меня всё нормально читается:

var
 Stream: TMemoryStream;
 I, J: Integer;
 Buf: array of Byte;
begin
 I := 1;
 Stream := TMemoryStream.Create;
 try
   Stream.Write(I, SizeOf(I));
   Stream.Position := 0;
   SetLength(Buf, SizeOf(Integer));
   Stream.Read(Buf[0], Length(Buf));
   Move(Buf[0], J, Length(Buf));
   ShowMessageFmt('I = %d; J = %d', [I, J])
 finally
   Stream.Free
 end
end.


Ega23   (2005-02-09 14:49:00) [17]

AFAIK, в INT386 семействе процессоров порядок битов идёт слева направо.
Т.е. integer будет выглядеть так 4-й байт, 3-й байт, 2-й байт, первый байт.

И если
var
i:Integer;

i:=1
то в памяти реально это будет выглядеть, как 01, 00, 00, 00


Aleksandr.   (2005-02-09 14:47:00) [18]

Ega23 ©  : ага. Оно самое.

Alexander Panov ©  :
В поток писалось Write(I,SizeOf(i));
Проблема началась с того, что потребовалось обеспечить совместимость новой и старой программы в работе с потоком на сокете. При этом новая однозначно в поток пишет integer и останавливается, а старая пишет туда большой и толстый массив байт. Поэтому для совместимости читаю буфер размером с integer и по его числу определяю, какой версией была сделана запись.


КаПиБаРа   (2005-02-09 14:46:00) [19]

Stream.Read(I,SizeOf(Integer));


Alexander Panov   (2005-02-09 14:42:00) [20]

А записывал в поток число как?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо