Je veux stocker un int de 4 octets dans un tableau de caractères ... tel que les 4 premiers emplacements du tableau de caractères soient les 4 octets du entier.
Ensuite, je veux retirer l’intérieur du tableau ...
Aussi, des points bonus si quelqu'un peut me donner du code pour le faire en boucle ... IE en écrivant comme 8 ints dans un tableau de 32 octets.
int har = 0x01010101;
char a[4];
int har2;
// write har into char such that:
// a[0] == 0x01, a[1] == 0x01, a[2] == 0x01, a[3] == 0x01 etc.....
// then, pull the bytes out of the array such that:
// har2 == har
Merci les gars!
EDIT: Supposer que int
sont 4 octets ...
EDIT2: S'il vous plaît ne vous souciez pas de l'endianité ... Je vais me soucier de l'endianité. Je veux juste différentes façons d’atteindre ce qui précède en C/C++. Merci
EDIT3: Si vous ne le savez pas, j'essaie d'écrire une classe de sérialisation au bas niveau ... alors je recherche différentes stratégies pour sérialiser certains types de données courants.
Ce n’est pas le moyen le plus optimal, mais c’est un coffre fort.
int har = 0x01010101;
char a[4];
a[0] = har & 0xff;
a[1] = (har>>8) & 0xff;
a[2] = (har>>16) & 0xff;
a[3] = (har>>24) & 0xff;
Sauf si vous vous souciez de l'ordre des octets, memcpy
fera l'affaire:
memcpy(a, &har, sizeof(har));
...
memcpy(&har2, a, sizeof(har2));
Bien sûr, il n’existe aucune garantie que sizeof(int)==4
s’applique à une implémentation particulière (et il existe des implémentations du monde réel pour lesquelles cela est en fait faux).
Écrire une boucle devrait être trivial à partir d'ici.
int main() {
typedef union foo {
int x;
char a[4];
} foo;
foo p;
p.x = 0x01010101;
printf("%x ", p.a[0]);
printf("%x ", p.a[1]);
printf("%x ", p.a[2]);
printf("%x ", p.a[3]);
return 0;
}
N'oubliez pas que le a [0] contient le LSB et le [3] le MSB, sur une petite machine endian.
#include <stdio.h>
int main(void) {
char a[sizeof(int)];
*((int *) a) = 0x01010101;
printf("%d\n", *((int *) a));
return 0;
}
Garder en tete:
Un pointeur sur un objet ou un type incomplet peut être converti en un pointeur sur un autre type d'objet ou incomplet. Si le pointeur résultant n'est pas correctement aligné pour le fichier pointé sur le type, le comportement est indéfini.
Remarque: L’accès à une union par un élément qui n’était pas le dernier attribué à un comportement indéfini . caractère si
char arr[4];
int a = 5;
arr[3] = a & 0xff;
arr[2] = (a & 0xff00) >>8;
arr[1] = (a & 0xff0000) >>16;
arr[0] = (a & 0xff000000)>>24;
obligerait arr [0] à conserver l'octet le plus significatif et arr [3] le moins.
edit: Juste pour que vous compreniez le tour & c'est un peu sage 'et' où && est logique 'et' . Merci aux commentaires sur le décalage oublié.
N'utilisez pas les syndicats, précise Pavel:
C'est U.B., parce que C++ interdit accéder à un membre du syndicat autre que le dernier qui a été écrit à. Dans En particulier, le compilateur est libre de optimiser l’affectation à
int
membre complètement avec le code ci-dessus, puisque sa valeur n'est pas utilisé ultérieurement (il ne voit que le suivant lu pour le membrechar[4]
et n’a aucune obligation de lui donner une valeur significative) . En pratique, g ++ en particulier est connu pour tirer de telles astuces, alors ceci ce n'est pas que de la théorie. D'autre part, en utilisantstatic_cast<void*>
suivi destatic_cast<char*>
est garanti à travail.
- Pavel Minaev
Vous pouvez également utiliser le placement new pour cela:
void foo (int i) {
char * c = new (&i) char[sizeof(i)];
}
#include <stdint.h> int main (int argc, char * argv []) { /* 8 ints dans une boucle */ int i; int * intPtr int intArr [8] = {1, 2, 3, 4, 5, 6, 7, 8}; char * charArr = malloc (32); pour (i = 0; i <8; i ++) { intPtr = (int *) & (charArr [i * 4]); /* ^ ^ ^ ^ */ /* pointe sur | | | */ /* cast as int * | | */ /* Adresse de | */ /* Emplacement dans le tableau de caractères */ * intPtr = intArr [i];/* write int à l’emplacement indiqué */ } /* Lire ints */ pour (i = 0; i <8; i ++) { intPtr = (int *) & (charArr [i * 4]); intArr [i] = * intPtr; } char * myArr = malloc (13); int myInt; uint8_t * p8;/* nombre entier non signé de 8 bits */ uint16_t * p16;/* nombre entier non signé de 16 bits */ uint32_t * p32;/* nombre entier non signé de 32 bits */ /* Utilisation de tailles autres que les 4 octets, */ /* définit tous les bits de myArr sur 1 */ p8 = (uint8_t *) & (myArr [0]); p16 = (uint16_t *) & (myArr [1]); p32 = (uint32_t *) & (myArr [5]); * p8 = 255; * p16 = 65535; * p32 = 4294967295; /* Récupère les valeurs */ p16 = (uint16_t *) & (myArr [1]); uint16_t my16 = * p16; /* Mettez le 16 bit int dans un int */.__ régulier. myInt = (int) my16; }
char a[10];
int i=9;
a=boost::lexical_cast<char>(i)
trouvé que c’est le meilleur moyen de convertir char en int et vice-versa.
une alternative à boost :: lexical_cast est sprintf.
char temp[5];
temp[0]="h"
temp[1]="e"
temp[2]="l"
temp[3]="l"
temp[5]='\0'
sprintf(temp+4,%d",9)
cout<<temp;
la sortie serait: hell9
valeur syndicale { int i; char octets [sizof (int)]; }; valeur v; v.i = 2; char * octets = v.bytes;