El registro y los registros de variantes en Delphi se reproducen https://blog.csdn.net/yt_maomao/article/details/36631133

// El tipo entero es exactamente de 4 bytes, el tipo ShortInt es de 1 byte, pero la memoria en Windows tiene 4 bytes asignados,
// Entonces, en realidad, aquí hay 4 bytes, puede ver el tamaño de este registro con SizeOf 8 bytes, aunque desperdicia
espacio, pero se acelera (el principio de alineación de límites en la asignación de memoria de Windows)
TPerson = registro
Edad: Entero;
Sexo: ShortInt;
final;
TPackedPerson = registro lleno
Edad: Entero;
Sexo: ShortInt; // Use el registro empaquetado, puede ver que el tamaño de este registro es de 5 bytes con Sizeof;
end;

TEmployee =
ID de registro : Integer; // Integer es 4 bytes,
caso Integer de
0: (YearMoney: Integer); / / YearMoney y MonthMoney comparten memoria, de acuerdo con la asignación máxima de memoria
1: (MonthMoney: ShortInt); // El tamaño del registro es de 8 bytes
finales;

TTagEmployee =
ID de registro : Entero;
Grado de caso: Entero de // Variable de grado se agrega aquí
0: (YearMoney: Integer); // YearMoney y MonthMoney comparten memoria, de acuerdo con la asignación máxima de memoria
1: (MonthMoney: ShortInt); // El tamaño del registro es de 12 bytes (ID + Grade + YearMoney)
final;

 

1. En DELPHI, usamos la palabra clave record para indicar un registro. A veces, también veremos el registro declarado con el registro empaquetado. La diferencia entre los dos radica en el método de almacenamiento; en Windows, la memoria La asignación es de 4 bytes a la vez, y Packed aplica y asigna memoria por byte, lo que es más lento porque requiere tiempo adicional para ubicar el puntero. Por lo tanto, si no se usa Empaquetado, Delphi solicitará memoria en forma de 4 bytes a la vez, por lo que si una variable no tiene 4 bytes de ancho, ¡también ocupará 4 bytes! Esto desperdicia algo de espacio, pero mejora la eficiencia.

2. Reglas para la grabación de variantes:

       (1) El tamaño de Long String, WideString, Dynamic Array e Interface son todos tamaños de puntero. OleVariant es en realidad la estructura VARIANT en el SDK COM, y el tamaño es de 16 bytes. Pero en Object Pascal, todos deben finalizarse automáticamente. Si aparecen en la parte variante, el compilador no puede saber si deberían finalizarse, porque no saben qué tipo está almacenado actualmente, por lo que no pueden aparecer en la variable. En el tipo de registro del cuerpo, o use una Cadena similar [10] para definir;

(2) Todos los campos variantes comparten una sección de memoria, y el tamaño de la memoria compartida está determinado por el campo variante más grande, la variable "más larga";

(3) Cuando existe la etiqueta, también es un campo del registro. Tampoco puede haber ninguna etiqueta. 

(4) El campo de condición de la parte variante del registro debe ser un tipo ordenado; el tipo que sigue al caso debe ser un tipo ordenado como booleano, entero, etc.

(5) El tipo de registro puede contener una parte variante, un poco como una declaración de caso, pero no hay un final final. La parte variante debe ser posterior a la declaración de otros campos en el registro.

3. El registro de variante más clásico, la estructura TMessage en Delphi:

La estructura de variantes, también conocida como el registro de variantes, es un concepto relativamente complejo. Los expertos no recomiendan su uso.

 

Un entero sin signo más grande (Cardinal) es 4294967295, su tamaño es de 4 bytes, su representación binaria es: 
11111111 11111111 11111111 11111111
su valor de byte bajo es 11111111, que es 255 decimal

// Prueba:
var
c: Cardinal;
begin
c: = 4294967295;
ShowMessage (IntToStr (Lo (c))); {mostrará: 255; Lo es la función para obtener el valor de byte bajo}
end;
el valor máximo de un tipo de Byte Es 255, su tamaño es de 1 byte, que se expresa en binario: 11111111
Si se asigna un valor de tipo Cardinal a un valor de tipo Byte, Byte solo tomará el byte más bajo de Cardinal.
// Prueba:
var
c: Cardenal;
b: Byte;
comenzar
c: = 4294967295;
b: = c;
ShowMessage (IntToStr (b)); {255}

c: = 258; {representación binaria: 00000000 00000000 00000001 00000010}
b: = c; {b will Solo obtenga: 00000010}
ShowMessage (IntToStr (b)); {2}
end;
esto es si podemos pensar, cuando se almacenará la estructura, un espacio donde se puede almacenar Cardinal, por supuesto, también puede colocar un valor de Byte;
si esto Los valores son, no necesitamos dos espacios de almacenamiento en absoluto.
Supongo que esta debería ser la intención original del registro de variantes de diseño de Delphi.
// Si existe tal formulario de registro de empleado,
escriba
TpersonRec =
ID de registro : Entero; {número de empleado}
caso booleano de {según clasificación}
Verdadero: (A: Cardenal); {si es un accionista, registre el salario anual}
Falso: (B: Word ); {Si no es así, registre el salario diario}
final;
var
personRec: TpersonRec;
comience
{calcule primero el tamaño de esta estructura:
ID es de tipo entero, debe tener un tamaño de 4 bytes;
A es de tipo cardinal, también debe tener 4 palabras Tamaño de sección;
B es de tipo Word, que debe tener un tamaño de 2 bytes;
total de 10 bytes.
}
{En realidad, TpersonRec tiene solo 8 bytes}
ShowMessage (IntToStr (SizeOf (TpersonRec))); {8}
{
motivo Sí: el campo A y el campo B comparten un espacio de almacenamiento; por
supuesto, este espacio de almacenamiento depende del tamaño grande, que es de 4 bytes de tamaño cardinal.
}
// Prueba de asignación:
personRec.ID: = 110;
personRec.A: = 100000; {Sé que es un accionista de un vistazo}
// Valor:
ShowMessage (IntToStr (personRec.A)); {100000; Esto no puede estar mal, cien mil océanos}
// Pero:
ShowMessage (IntToStr (personRec.B)); {34464? ¿Es este el salario diario del trabajador? }
{
Primero, los dos campos A y B ocupan el mismo espacio, y uno de ellos tiene un valor, y el otro por supuesto tiene un valor,
pero debido a la diferente capacidad del tipo de datos, sus valores pueden ser diferentes.
En muchos casos A continuación, es posible que no nos importe otro valor, pero si realmente es necesario , consulte
el siguiente ejemplo:
}
end;

escriba
TpersonRec =
ID de registro : Entero;
etiqueta de caso: booleano de {Aquí se agregó una variable de etiqueta}
True: (A: Cardinal);
False: (B: Word);
end;
var
personRec: TpersonRec;
begin
{Podemos usar la variable de etiqueta para distinguir, quién es el valor de la parte variante en el registro, por ejemplo:}
personRec.ID: = 110;
personRec.tag: = True;
personRec.A: = 100000; {salario del accionista anual}
personRec.ID: = 111;
personRec.tag: = False;
personRec.B: = 100; {salario diario del trabajador}
end;

// La estructura variante más clásica es la estructura TMessage definida por Delphi, los dos grupos de datos están en uno, ¡Qué inteligente!
TMessage = registro empaquetado
Msg: Cardinal; Case
Integer of
0: (
WParam: Longint;
LParam: Longint;
Result: Longint);
1: (
WParamLo: Word;
WParamHi: Word;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
fin;

Los registros (registros)
(similares a las estructuras en otros idiomas) representan una colección de diferentes tipos de elementos, cada elemento se llama un "campo", y cuando declara un tipo de registro,
debe especificar un nombre y tipo para cada campo. La sintaxis para declarar registros es
type recordTypeName = record
fieldList1: type1;
...
fieldListn: typen;
end
Aquí, recordTypeName es un identificador válido, cada tipo representa un tipo y cada fieldList es un identificador válido o está
separado por una coma Para la secuencia de identificador abierto, el último punto y coma es opcional. (¿Qué punto y coma? ¿Es el último campo o después del final?) Por
ejemplo, la siguiente declaración declara un tipo de registro TDateRec:
tipo
TDateRec = record
Año: entero;
Mes: (enero, febrero, marzo, abril, mayo, Junio, julio, agosto, septiembre, octubre, noviembre, diciembre);
Día: 1..31;
fin;
TDateRec contiene 3 campos: un tipo entero Año, un tipo enumerado Mes y otro tipo de sub-límite Día. Estándar
Chi Fu año, mes y día son TDateRec campo, se comportan como variables. La declaración no
asigna memoria para Año, Mes y Día , solo se asigna cuando se instancia, como lo siguiente:
var Record1, Record2: TDateRec;
La declaración de variables anterior crea dos instancias TDateRec, llamadas Record1 y Record2.
Puede usar el nombre del registro como calificador y acceder al campo por el nombre del campo:
Record1.Year: = 1904;
Record1.Month: = Jun;
Record1.Day: = 16;
o use la instrucción
with : con Record1 do
begin
Year: = 1904;
Mes: = junio;
día: = 16;
fin;
ahora, puede copiar el valor de Registro1 en Registro2:
Registro2: = Registro1;
Debido a que el alcance del nombre del campo se limita al registro en sí, no necesita preocuparse por el conflicto entre el nombre del campo y otras variables.
En lugar de definir tipos de registro, puede usar la construcción de registro ... directamente en declaraciones de variables:
además de definir tipos de registro, también puede usar registro ... para construir variables de declaración directa:
var S:
nombre de registro : cadena;
Edad: entero;
terminar;
sin embargo, esto no le permite volver a utilizar declaración de tipo, y este tipo de declaración no es una asignación compatible, incluso si ellos (grabación) de
estructura idéntica.

Partes variantes en registros
Un tipo de registro puede tener una parte variante. Parece una declaración de caso. En la declaración, la parte variante debe seguir otros campos.
Para declarar un registro de variante, use la siguiente sintaxis:

tipo recordTypeName = registro
fieldList1: type1;
...
fieldListn: typen;
etiqueta de caso: ordinalType of
constantList1: (Variant1);
...
constantListn: (Variantn);
end;
la parte anterior de la declaración (hasta el caso de la palabra clave) y registros estándar El tipo es el mismo. El resto de la declaración (desde el caso hasta el último
punto y coma opcional ) se denomina parte variante. En la parte variante, la
 etiqueta es opcional y puede ser cualquier identificador válido. Si omite la etiqueta, también omita los dos puntos (:) después de ella.
 ordinalType representa un tipo ordenado.
 Cada constantList representa una constante de tipo ordinalType, o una secuencia de constantes separadas por comas. Entre todas las constantes
, un valor no puede aparecer varias veces.
 Cada Variante es una lista de declaraciones separadas por comas similares a fieldList: type, es decir, Variant tiene la siguiente
forma:
fieldList1: type1;
...
fieldListn: typen;
Aquí, cada fieldList es un indicador válido Carácter, o una lista de identificadores separados por comas, cada tipo representa un tipo, y el
último punto y coma es opcional. Estos tipos no pueden ser cadenas largas, matrices dinámicas, tipos de variantes o interfaces (todos pertenecen a la gestión dinámica
Tipos de gestión), no puede ser un tipo de estructura que contenga los tipos anteriores, pero pueden ser punteros a estos tipos.
sintaxis compleja registro variante de tipo, la semántica, pero muy simple: una parte de grabación variante contiene varios tipos de variantes, que comparten la misma área de memoria
de dominio. Puede leer o escribir en cualquier campo de cualquier tipo de variante en cualquier momento, pero cuando cambia un
campo de una variante y un campo de otra variante, puede sobrescribir Datos propios Si una etiqueta, que al igual que la grabación de
parte del cuerpo -invariant un campo adicional, que es de tipo ordinalType.
La parte variante tiene dos propósitos. Primero, suponga que desea crear un registro cuyos campos tienen diferentes tipos de datos, pero sabe
que nunca necesita todos los campos en una instancia (registro), por ejemplo:
escriba
TEmployee = record
FirstName, LastName: string [ 40];
Fecha de nacimiento: TDate;
caso Salario : Booleano de
verdadero: (Salario anual: Moneda);
Falso: (Salario por hora: Moneda);
final;
la idea aquí es que cada empleado es un salario anual o un salario por hora, pero no ambos Todos ellos Por lo tanto, cuando crea una
instancia de TEmployee , no es necesario asignar memoria para cada campo. En el caso anterior, la única diferencia entre las variantes es el nombre del campo, pero el
caso más simple es que los campos tienen diferentes tipos. Eche un vistazo a un ejemplo más complicado:
escriba
TPerson = record
Nombre, Apellido: cadena [40];
Fecha de nacimiento: TDate;
Caso Ciudadano: Booleano de
Verdadero: (Lugar de nacimiento: cadena [40]);
Falso: (País: cadena [20];
EntryPort: cadena [20];
EntryDate, ExitDate: TDate);
end;
type
TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);
TFigure = record
case TShapeList of
Rectangle: (Height, Width: Real);
Triangle: (Side1, Side2, Angle: Real);
Circle: (Radio: Real);
Elipse, Otro: ();
fin;
Para cada instancia de tipo de registro, el compilador asigna suficiente memoria para acomodar todos los campos del tipo de variante más grande. Código opcional y
constantLists (como en el ejemplo anterior rectángulo, triángulo, etc.) no tienen efecto en el campo de la gestión del compilador, que son sólo para la
conveniencia del programador.
La segunda razón para usar registros de variantes es que puede tratar los mismos datos como tipos diferentes, incluso si el compilador no permite clases
Tipo de ocasiones de conversión. Por ejemplo, en un tipo de variante, el primer campo es un número real de 64 bits, en otro tipo de variante, el primer
campo es un número entero de 32 bits, puede asignar un valor a un número real (campo), y luego Úselo como un entero para leer su primer valor de 32 bits (por ejemplo, páselo
a una función que requiera parámetros enteros).
————————————————
Declaración de derechos de autor: Este artículo es un artículo original del blogger de CSDN "_ 毛毛 _", siga el acuerdo de copyright CC 4.0 BY-SA, adjunte el enlace original y vuelva a imprimir Esta declaración
Enlace original: https://blog.csdn.net/yt_maomao/article/details/36631133

Supongo que te gusta

Origin www.cnblogs.com/QuincyYi/p/12730132.html
Recomendado
Clasificación