Слишком поздно, но может помочь. Я сделал для базы 10, если вы меняете базу, вам нужно позаботиться о том, как вычислить цифру 0 в *p-'0'
.
Я бы использовал правило Хорнера для вычисления значения.
#include
void main(void)
{
char *a = "5363", *p = a;
int unsigned base = 10;
long unsigned x = 0;
while(*p) {
x*=base;
x+=(*p-'0');
p++;
}
printf("%lu\n", x);
}
Вы также можете использовать ключевое слово absolute, чтобы заставить обе структуры использовать один и тот же адрес памяти:
var
Data: array[1..SizeOf(TMyStruct)] of byte;
s : TMyStruct absolute Data;
Любые данные, записанные в S, также доступны как Data без необходимости выполнять перемещение или преобразование указателя .
Это может быть сложно, поскольку вам нужно убедиться, что макеты исходной и целевой структуры идентичны. Если да, то у вас есть 2 варианта: либо использовать указатель на массив данных, либо использовать копию памяти:
Указатель:
type
// Declare a pointer type for your struct.
PMyStruct = TMyStruct^;
...
var
ptr: PMyStruct;
begin
ptr := PMyStruct(Cardinal(@Data));
// use ptr...
end;
Копия памяти:
var
Data: array of Byte;
s: TMyStruct;
begin
// fill Data...
if SizeOf(s) <> Length(Data) then
raise Exception.Create('Input size is not the same size as destination structure.');
CopyMemory(@s, @Data, Length(Data));
// use s...
end;
Вы можете делать в Delphi именно то, что вы делали бы в C ++. Тем не менее, определите именованный тип для указателя записи, поскольку Delphi не позволяет вам определять типы в операторах.
type
PPacket = ^TPacket;
var
packet: PPacket;
packet := PPacket(@data[0]);
Я использовал @data [0]
, потому что он работает независимо от того, данные - это динамический массив. Если это динамический массив, то data
на самом деле является указателем на первый байт пакета, так что это будет работать:
packet: = PPacket (data); // только для динамического массива тогда data
на самом деле является указателем на первый байт пакета, поэтому это будет работать:
package: = PPacket (data); // только для динамического массива тогда data
на самом деле является указателем на первый байт пакета, поэтому это будет работать:
package: = PPacket (data); // только для динамического массива
Но если данные
являются не динамическим массивом, то это приведение типа будет недействительным. Вместо этого вам нужно будет преобразовать указатель в data
, например:
packet: = PPacket (@data); // только для статического массива
Это не сработает, если это динамический массив. Первый код будет работать в обоих случаях. Но если у вас включена проверка диапазона (а вы, вероятно, должны это сделать), то я думаю, что первый код вызовет исключение, если data
является динамическим массивом нулевой длины, поэтому будьте осторожны.
Если вы хотите чтобы вместо этого перейти по маршруту C #, где вы копируете байты из массива в отдельную переменную TPacket
, я бы использовал это:
var
packet: TPacket;
// Source param comes first. Params are passed by
// reference automatically.
Move(data[0], packet, SizeOf(packet));
Вам нужно убедиться, что data
содержит достаточно байтов для заполнения всего значения TPacket
. TPacket
лучше не содержать никаких типов, управляемых компилятором, таких как строка
, вариант
, IUnknown
или типы динамического массива. Ни приведение типов указателя, ни Move
в этом случае не работают должным образом.