3
votes

Existe-t-il un moyen de déterminer le type d'un pointeur?

Disons que j'ai ces types et variables:

function DoSomething(P: Pointer);
begin
 //if  ??? Type(P) = PMyStruct1 ??? then ....

J'ai une fonction qui accepte Pointer comme argument. Existe-t-il un moyen de déterminer si la fonction est appelée avec la variable P1 ou P2?

Quelque chose comme:

type

TMyStruct1 = record
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct1 = ^TMyStruct1;

TMyStruct2 = record
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct2 = ^TMyStruct2;

var

P1: PMyStruct1;
P2: PMyStruct2; 


6 commentaires

L'introspection est généralement une fonctionnalité des langages interprétés (Java, C #, Python). Les langages compilés (C ++, Delphi) ne l'implémentent généralement pas de manière native.


Non, vous ne pouvez pas déterminer si la fonction a été appelée avec P1 ou P2.


Vous ne pouvez même pas déterminer si vous avez un pointeur valide ou non.


FWIW, au lieu d'enregistrements, pensez à utiliser des classes simples. Vous pouvez vérifier le type d'une instance de classe.


Si vous n'avez besoin que du type d'une variable, alors avec certaines réserves, cela peut être réalisé en utilisant des génériques.


@Vasek Non, ce n'est pas le cas. Il n'y a pas de solution à cette question basée sur les génériques.


3 Réponses :


4
votes

Existe-t-il un moyen de déterminer si la fonction est appelée avec la variable P1 ou P2?

Non, il n'y en a pas.


0 commentaires

3
votes

Vous pouvez y parvenir en ajoutant un "en-tête standard" à votre structure. Dans votre cas, un simple champ indiquant le type de votre structure suffirait.

const 
  STRUCT_1 = 1;
  STRUCT_2 = 2;
type

TMyStruct1 = record
  StructType  : Integer
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct1 = ^TMyStruct1;

TMyStruct2 = record
  StructType  : Integer
  Int1        : Integer;
  Int2        : Integer;
  Str1        : String;
  Str2        : String;
end;
PMyStruct2 = ^TMyStruct2;

var

P1: PMyStruct1;
P2: PMyStruct2;

function DoSomething(P: Pointer);
begin
  case PInteger(P)^ of //points to StructType
    STRUCT_1 : ;
    STRUCT_2 : ;
  end;
end;

Celui qui appelle votre fonction serait responsable de bien alimenter le champ StructType .

Comme mesure de compatibilité ascendante, vous pouvez également ajouter un champ "StructSize" au cas où vous auriez besoin de plusieurs versions de chaque structure.

Ce type de vérification de type est "faible" , dans le sens où il n'y a aucune garantie que le pointeur soit du bon type, il vérifie seulement si les 4 premiers octets vers lesquels il pointe contiennent STRUCT_1 ou STRUCT_2.

Maintenant, si vous ne contrôlez pas la définition de ces disques, vous n’avez pas de chance.


7 commentaires

"si vous ne contrôlez pas la définition de ces enregistrements, vous n'avez pas de chance" - Une fois que vous sortez de son contexte, il ne l'est pas. Par exemple, modifiez la définition de la fonction pour accepter un paramètre de type struct ...


Je veux dire, la réponse à la question est clairement non. Il semble que cela répond à une question différente. Et comme le dit @sertac, si vous êtes prêt à changer les règles, vous pouvez bien sûr obtenir une réponse différente.


@SertacAkyuz ... ou comme ce point, déclarez 2 fonctions comme DoSomething1 (P: Pointer) et DoSomething2 (P: Pointer) .


@DavidHeffernan La réponse est clairement OUI, c'est possible. Certes, pour pouvoir le faire, il y a des conditions préalables. Et malheureusement, vous ne pouvez pas, à partir du seul pointeur, valider que ces conditions préalables sont remplies. Ce que je décris ici, c'est à peu près comment fonctionne l'opérateur SI pour TObject. Donc, bien que la détermination du type d'un pointeur choisi au hasard soit, en effet, impossible (ou à tout le moins, incroyablement peu fiable), répondre à un simple «non» à cette question me semble assez incomplet.


La réponse est clairement non, vous ne pouvez pas, pour la question posée par le demandeur.


Vous avez tous les deux des points valides, je ne peux donc accepter qu'une seule des réponses


@GeorgiBonchev Vous pouvez accepter une réponse. Vous décidez lequel répond le mieux à la question que vous avez posée et acceptez cela. Personne n'a de problème à vous en choisir un.



0
votes

Un pointeur est une sorte de variable qui peut stocker une adresse mémoire ou un Valeur nul .

Il peut pointer vers n'importe quoi, vers un objet valide ou invalide, déjà détruit, vers une variable, vers un troisième caractère dans une chaîne ou vers un autre pointeur.

Mais il ne stocke que l'adresse mémoire, rien de plus. Il n'existe aucun moyen de connaître le type à partir d'une adresse mémoire. Si vous avez besoin du type ou d'autres informations, vous devez vous en occuper.

Pour les structures homogènes, une approche consiste à stocker son type ou sa version dans le premier octet de la structure et à pointer plus tard un PStructureX correspondant sur l'adresse du pointeur, comme dans la réponse de Ken.


0 commentaires