Как вы получаете доступ к различным типам данных с помощью указателей Pascal?

В общем, у меня проблема с выяснением того, как обрабатывать преобразования указателей в паскале. Если бы мне нужно было слово из моего указателя байта, я бы не сделал что-то вроде:

type WordPtr = ^Word;
var P1, P2 : ^Byte; w, byteoffset : word; 
begin 
  P1:=SomeGetMemVar;  byteoffset:=8;
  w:=WordPtr(@P1^[byteoffset])^; { invalid qualifiers at the [ }
  w:=WordPtr(P1[byteoffset])^; { invalid qualifiers at the [ }
  w:=WordPtr(P1+byteoffset)^; { type mismatch }
end;

По-видимому, нет, потому что это не работает, как показано в комментариях.

Как заставить это работать на Паскале? С будет:

uint16_t byteoffset=8;
uint8_t* P1=(uint8_t*) malloc(1000);
uint16_t w;
w=*((uint16_t*) (P1+byteoffset));   // method 1
w=*((uint16_t*) (&P1[byteoffset])); // method 2

Спасибо!

Это немного отличается в зависимости от версии. Непосредственная причина ошибки в том, что ^Byte не является массивом. Вместо этого вы можете объявить type TByteArray = array[0..65535] of byte;, а затем type PByteArray = ^TByteArray;, а затем использовать PByteArray вместо ^Byte выше. При этом ваша первая попытка должна скомпилироваться.

500 - Internal Server Error 17.02.2023 23:22
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Laravel - это мощный PHP-фреймворк, используемый для создания масштабируемых и надежных веб-приложений. Одним из преимуществ Laravel является его...
Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание API-ресурса Laravel может быть непростой задачей. Она требует глубокого понимания возможностей Laravel и лучших практик, чтобы обеспечить...
Как сделать компонент справочного центра с помощью TailwindCSS
Как сделать компонент справочного центра с помощью TailwindCSS
Справочный центр - это веб-сайт, где клиенты могут найти ответы на свои вопросы и решения своих проблем. Созданный для решения многих распространенных...
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
0
1
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если ваш пример - это то, что вы пытаетесь сделать, то есть просто извлечь один байт слова, вам не нужно выполнять все эти манипуляции с указателем. Попробуй это:

uses System.SysUtils;
type WordPtr = ^WordRec;
var w:  word;
    p1: WordPtr;
begin
  p1=GetSomeMemVar;
  w:=p1.Hi;
end;

WordRec — это запись с двумя байтовыми полями в пространстве слова, так что вы можете получить доступ к каждому байту слова. В SysUtils также есть LongRec и Int64Rec, и все они имеют варианты частей, так что вы можете получить доступ к отдельным байтам или отдельным словам и т. д. или рассматривать их как массивы. И вы всегда можете создать свои собственные подобные записи.

Если вы хотите продолжить работу с указателями, см. https://docwiki.embarcadero.com/RADStudio/Sydney/en/Pointer_Math_%28Delphi%29

Ответ принят как подходящий

Чтобы обрабатывать указатели как массивы, убедитесь, что включена функция {$POINTERMATH ON}. Это уже для PByte (не используйте ^Byte напрямую), но не для большинства типов указателей по умолчанию.

Попробуйте еще что-нибудь вроде этого:

{$POINTERMATH ON}
var
  P1 : PByte;
  w, byteoffset : Word;
begin 
  P1 := SomeGetMemVar;
  byteoffset := 8;
  w := PWord(@P1[byteoffset])^;
  //or:
  w := PWord(P1+byteoffset)^;
end;

В качестве альтернативы используйте Move() вместо указателей приведения:

var
  P1 : PByte;
  w, byteoffset : Word;
begin 
  P1 := SomeGetMemVar;
  byteoffset := 8;
  Move(P1[byteoffset], w, SizeOf(w));
  //or:
  Move((P1+byteoffset)^, w, SizeOf(w));
end;

Для более старых компиляторов, которые не поддерживают {$POINTERMATH}, вы можете привести тип к PAnsiChar (который всегда поддерживал математику указателя по умолчанию):

var
  P1 : PByte;
  P2: PAnsiChar;
  w, byteoffset : Word;
begin 
  P1 := SomeGetMemVar;
  P2 := PAnsiChar(P1);
  byteoffset := 8;
  w := PWord(@P2[byteoffset])^;
  //or:
  w := PWord(P2+byteoffset)^;
end;

Или просто увеличьте указатель PByte вручную:

var
  P1, P2 : PByte;
  w, byteoffset : Word;
begin 
  P1 := SomeGetMemVar;
  byteoffset := 8;
  P2 := P1;
  Inc(P2, byteoffset);
  w := PWord(P2)^;
end;

Другие вопросы по теме