Question
Je travaille sur un projet où je dois traiter au niveau octet avec des entiers. Comme économiser de l'espace est une considération primordiale, je n'ai besoin que de très petites tailles (et de longueurs variables).
Existe-t-il un moyen de convertir l’int 4096 en 3 octets? ou '1053' dans 2 octets?
Évidemment, je peux le faire manuellement = (octet [0] * 256) + (octet [1]), mais je me demandais s’il existait une option plus facile pour convertir l’int en x octets et revenir?
La solution
Pouvez-vous? Sûr. Cela économisera-t-il de la place? Peut-être, selon le travail que vous voulez faire. Vous devez comprendre que le processeur est 32 bits, ce qui signifie qu'il a 4 registres d'octets, donc c'est comme ça qu'il va vouloir stocker et accéder à des choses. Pour forcer un 3 octets "int" vous devrez le conserver dans un tableau d'octets et l'extraire du tableau en une adresse alignée avant utilisation. Cela signifie que si vous le stockez rapidement, le compilateur le compilera (et vous perdrez toute efficacité que vous pensez avoir créée) ou la lecture et l’écriture seront beaucoup plus lentes.
S'il s'agit d'une application de bureau, en quoi l'économie de l'espace est-elle une considération primordiale, en particulier lorsque vous parlez d'un octet par élément? La pénalité de perf pour l’accès à l’élément peut vous faire oublier l’importance de cet octet.
Je dirais que si ce 1 octet est vraiment important, vous utilisez peut-être le mauvais langage de toute façon. Le nombre d'octets que vous sauvegarderiez si vous n'avez pas installé ni utilisé le CLR est un lot de ces octets.
Note latérale: vous feriez aussi un quart de travail, pas une multiplication (bien que le compilateur y arrive probablement pour vous).
Autres conseils
Juste pour ajouter de la folie, faisons-le en C # en utilisant le vieux truc de l'union dans le style C:
[StructLayout(LayoutKind.Explicit)]
struct OddUnion
{
/* The 32-bit integer value */
[FieldOffset(0)]
public int IntegerValue;
/* The bytes that overlap with it */
[FieldOffset(0)]
public byte Byte1;
[FieldOffset(1)]
public byte Byte2;
[FieldOffset(2)]
public byte Byte3;
[FieldOffset(3)]
public byte Byte4;
}
Ensuite, lorsque vous souhaitez "convertir", procédez comme suit:
OddUnion myOddUnion;
myOddUnion.IntegerValue = 4096;
Byte secondByte = myOddUnion.Byte1;
Mais cela n’aidera vraiment que si vous cherchez à "enregistrer". le coût du décalage d'un bit d'un mot à partir d'un bit. Je n'ai pas examiné le SMIL généré, donc je ne sais pas si cela coûte moins cher par rapport à une autre solution.
Vous pouvez faire un codage entier de longueur variable. L'ancienne méthode d'il y a des années consistait à utiliser le bit haut de chaque octet pour indiquer que l'entier continue sur un autre octet. Donc, vous perdez un bit par octet, mais vous gagnez de petits entiers. Ceci est surtout utile dans le stockage persistant où chaque dernier octet compte.
Exemple: supposons que nous ayons affaire à des entiers non signés, nous aurions
int binary
0 00000000
1 00000001
...
127 01111111
128 00000001 10000000
129 00000001 10000001
...
255 00000001 11111111
256 00000010 10000000
...
16383 01111111 11111111
16384 00000001 10000000 10000000
so 0-127 prend 1 octet et 128-16383 prend 2 octets, etc ...
Pour des méthodes plus complexes, consultez cette page
. BitConverter.GetBytes
vous obtiendrez les octets.
et
BitConverter.ToInt32
vous obtiendrez un int de 32 bits à partir des octets.
Vous devez changer quelque peu. C'est beaucoup plus facile si vous travaillez avec HEX, car chaque nombre (je veux dire chaque chiffre, mais le chiffre correspond à la base 10, hex git) représente quatre bits.