Как вы получаете доступ к различным типам данных с помощью указателей 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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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;

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