Объединение байтовых массивов (через MidB / LeftB)

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Объединение байтовых массивов (через MidB / LeftB)

Сообщение ALX_2002 » 26.03.2015 (Чт) 13:03

Приветствую жителей форума ! Понимаю, что эта тема уже рассматривался многократно. Тут в очередной раз потребовалось сделать объединение Byte() массивов. Полез в старые сохранённые исходники. Нашёл пару примеров

1) Первый, на мой взгляд самый кривой, создаётся третий массив на размер первого и второго, а затем в него через цикл For Next копируются байты из первых двух.

2) Второй - используется Api - CopyMemory. От первого примера отличается только отсутствием циклов.

Посмотрел на код... Первый пример отмёл сразу, задумался над вторым. Нужно объявлять Api, определять размерности массивов, проверять есть ли она вообще у них, а то вдруг массив ещё динамический и размер не установлен, потом смотреть границу начала у каждого... Уф.

А что если:

Код: Выделить всё
Function JoinByteArrays(Array1() As Byte, Array2() As Byte) As Byte()
    JoinByteArrays = MidB(Array1, 1) & MidB(Array2, 1)
End Function


В чём минусы такого варианта ? Скорость ? Излишнее копирование данных в памяти ? Не всегда сработает правильно ?

Заранее благодарю за комментарии :roll:

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Qwertiy » 26.03.2015 (Чт) 13:08

ALX_2002 писал(а):
Код: Выделить всё
Function JoinByteArrays(Array1() As Byte, Array2() As Byte) As Byte()
    JoinByteArrays = MidB(Array1, 1) & MidB(Array2, 1)
End Function

В чём минусы такого варианта ? Скорость ? Излишнее копирование данных в памяти ? Не всегда сработает правильно ?

Жуть. Всё перечисленное. Уж лучше цикл.

ALX_2002 писал(а):определять размерности массивов

Не помню, а LenB с массивами не прокатит?
Последний раз редактировалось Qwertiy 26.03.2015 (Чт) 13:08, всего редактировалось 1 раз.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Хакер » 26.03.2015 (Чт) 13:08

ALX_2002 писал(а):В чём минусы такого варианта ? Скорость ? Излишнее копирование данных в памяти ?


Запутанность на уровне кода.
Большое число лишних операций (создание BSTR на базе SafeArray и обратно).
Использование строковой кучи для промежуточного этапа — в ней банально может не хватить места под нужные данные.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Хакер » 26.03.2015 (Чт) 13:09

Qwertiy писал(а): Уж лучше цикл.

Не лучше.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.03.2015 (Чт) 13:12

Хакер писал(а):создание BSTR на базе SafeArray и обратно

А оно всегда корректно? А то что-то оно мне подозрительным кажется...

Хакер писал(а):Использование строковой кучи для промежуточного этапа

Не знал, что у строк есть отдельная куча...

Хакер писал(а):Не лучше.

Конвертирование в строку, конкатенация и конвертирование обратно лучше цикла? о_О
Почему?

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение ALX_2002 » 26.03.2015 (Чт) 13:15

Qwertiy писал(а):Жуть. Всё перечисленное. Уж лучше цикл.


Т.е и CopyMemory тоже плохо ? :shock:

Почему цикл лучше ? @_@

ALX_2002 писал(а):определять размерности массивов

Не помню, а LenB с массивами не прокатит?[/quote]

VB6 говорит:
Variable required - can't assign to this expression


P.S Qwertiy, Хакер - Если не сложно, можете показать как на Ваш взгляд правильнее реализовать такую функцию (объединения массивов) ?

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.03.2015 (Чт) 13:27

ALX_2002 писал(а):Т.е и CopyMemory тоже плохо ? :shock:

Нет, CopyMemory как раз хорошо. Если правильно использовать.

ALX_2002 писал(а):Variable required - can't assign to this expression

Assign? А ты точно то делаешь?

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Re:

Сообщение ALX_2002 » 26.03.2015 (Чт) 13:33

Qwertiy писал(а):Нет, CopyMemory как раз хорошо. Если правильно использовать.


Т.е тот вариант, который я описал в первом посте, неверен ?

Qwertiy писал(а):Assign? А ты точно то делаешь?


Уже не уверен. )

Код: Выделить всё
Private Sub Form_Load()
    Dim a() As Byte
    MsgBox LenB(a)
End Sub

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Хакер » 26.03.2015 (Чт) 13:53

Qwertiy писал(а):А оно всегда корректно? А то что-то оно мне подозрительным кажется...

Данные оно не искажает. Просто копирует контент строки в массив как есть.

Qwertiy писал(а):Не знал, что у строк есть отдельная куча...

Ну и зря. SysAllocString выделяет память не оттуда же, откуда выделяются блоки под массивы.
Значит ты никогда не встречал Run-time error 14 — Out of string space.

Qwertiy писал(а):Конвертирование в строку, конкатенация и конвертирование обратно лучше цикла? о_О
Почему?

Потому что в VB-шном цикле во-первых каждая итерация будет сопровождаться проверкой границ массивов (для исходного массива и массива назначения), если только не включена соответствующая оптимизацию, глобально отключающая такие проверки.

А во-вторых: для каждой итерации будет отдельная инструкция mov, достающая отдельно взятый байт из массива, и отдельно взятая инструкция mov, кладующая отдельный байт массив. Что очень медленно.

В то время как в варианте с CopyMemory будут использоваться rep movs dwords [edi], dword[esi], а затем до остатка rep movs byte[edi], byte[esi].

То есть «строковые» подвиды инструкций. Которые сами по себе оптимизированы для подобных операций и от того — быстрее, чем побайтовое копироание отдельными инструкциями. Кроме того, копирование большей части данных будет осуществлено 4-байтными порциями, а не байтами байтовыми, что тоже сильно увеличивает скорость.

ALX_2002 писал(а):Т.е и CopyMemory тоже плохо ? :shock:

Почему цикл лучше ? @_@

Почему с CopyMemory плохой вариант? Кто сказал? Это наиболее разумный вариант, если не доходить до в ряде случаев ещё более выгодного решения с пересмотром самой организации данных.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение ALX_2002 » 26.03.2015 (Чт) 14:41

:wink: Повторюсь:
Qwertiy, Хакер - Если не сложно, можете показать как на Ваш взгляд правильнее реализовать такую функцию (объединения байт массивов) ?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Хакер » 26.03.2015 (Чт) 15:57

ALX_2002 писал(а):Qwertiy, Хакер - Если не сложно, можете показать как на Ваш взгляд правильнее реализовать такую функцию (объединения байт массивов) ?

Объединить с сохранением одного из исходных массивов? Или без сохранения?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.03.2015 (Чт) 16:02

Хакер писал(а):Объединить с сохранением одного из исходных массивов? Или без сохранения?

Имелось в виду "с сохранением одного или обоих"?
Redim Preserve для первого и CopyMemory для хвоста vs новый массив и два CopyMemory?

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение ALX_2002 » 26.03.2015 (Чт) 16:16

Вот как раз эта мысль посетила, что нужно уточнить. Только собрался написать, а вы уже спросили :D . В принципе интересуют оба варианта.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Хакер » 26.03.2015 (Чт) 16:58

ALX_2002 писал(а):как на Ваш взгляд правильнее реализовать такую функцию (объединения байт массивов) ?

Например так:
Код: Выделить всё
Public Declare Sub RtlMoveMemory Lib "kernel32" (dst As Any, src As Any, ByVal length As Long)

Public Sub AryConcatB(a1() As Byte, a2() As Byte, ret() As Byte)
    Dim nElmCount1  As Long, iBase1 As Long
    Dim nElmCount2  As Long, iBase2 As Long
    Dim new_base    As Long
   
    If Not AryTestVectorAndGetBaseLen(a1, iBase1, nElmCount1) Then Err.Raise 5, , "a1 is not single-dimensioned!"
    If Not AryTestVectorAndGetBaseLen(a2, iBase2, nElmCount2) Then Err.Raise 5, , "a2 is not single-dimensioned!"
   
    If nElmCount1 = 0 And nElmCount2 = 0 Then
        Erase ret
        Exit Sub
    End If
   
    new_base = IIf(nElmCount1 > 0, iBase1, iBase2)
    ReDim ret(new_base To new_base + (nElmCount1 + nElmCount2) - 1)
   
    If nElmCount1 > 0 Then RtlMoveMemory ret(new_base), a1(iBase1), nElmCount1
    If nElmCount2 > 0 Then RtlMoveMemory ret(new_base + nElmCount1), a2(iBase2), nElmCount2
End Sub

Public Function AryTestVectorAndGetBaseLen(a() As Byte, iBase As Long, nLength As Long) As Boolean
    On Error Resume Next
    iBase = LBound(a, 1)
    nLength = UBound(a, 1) - iBase + 1
    On Error GoTo eh:
    VarPtr UBound(a, 2)
    Exit Function
eh: AryTestVectorAndGetBaseLen = True
End Function


Но я бы прежде чем писать, подумал, предстоит ли серия склеек, предстоят ли групповые склейки, есть ли смысл в обёртовании массивов в варианты и не лучше ли перейти на блочно-массивную организацию данных и вообще ничего не склеивать.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение ALX_2002 » 26.03.2015 (Чт) 17:05

Хакер писал(а):Но я бы прежде чем писать, подумал, предстоит ли серия склеек, предстоят ли групповые склейки, есть ли смысл в обёртовании массивов в варианты и не лучше ли перейти на блочно-массивную организацию данных и вообще ничего не склеивать.


1) Благодарю за код !

2) Рекомендацию понял. Буду думать )

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.03.2015 (Чт) 17:33

1. Если склеиваем 2 пустых массива, то результат не изменяется, т. е. не факт, что получится именно пустой массив?
2. Зачем On Error Resume Next? Что-то с пустыми массивами?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объединение байтовых массивов (через MidB / LeftB)

Сообщение Хакер » 27.03.2015 (Пт) 4:11

Qwertiy писал(а):. Если склеиваем 2 пустых массива, то результат не изменяется, т. е. не факт, что получится именно пустой массив?

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

Qwertiy писал(а):Зачем On Error Resume Next? Что-то с пустыми массивами?

Чтобы подавить ошибку в случае, если передали неинициализированный массив.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в Visual Basic 1–6

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

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

    TopList